Ускорители типа PowerShell: PSObject против PSCustomObject
В PowerShell v3.0 PSCustomObject
был представлен. Это как PSObject
, но лучше. Среди других улучшений (например, сохранение порядка свойств) создание объекта из хеш-таблицы упрощено:
[PSCustomObject]@{one=1; two=2;}
Теперь кажется очевидным, что это утверждение:
[System.Management.Automation.PSCustomObject]@{one=1; two=2;}
будет работать так же, потому что PSCustomObject
это псевдоним для полного пространства имен + имя класса. Вместо этого я получаю ошибку:
Невозможно преобразовать значение "System.Collections.Hashtable" типа "System.Collections.Hashtable" в тип "System.Management.Automation.PSCustomObject".
Я перечислил ускорители для обоих типов объектов:
[accelerators]::get.GetEnumerator() | where key -Like ps*object
Key Value
--- -----
psobject System.Management.Automation.PSObject
pscustomobject System.Management.Automation.PSObject
и обнаружил, что оба ссылаются на одно и то же PSObject
класс - это должно означать, что использование ускорителей может сделать кучу других вещей, а не просто сделать код короче.
Мои вопросы по этому вопросу:
- У вас есть интересные примеры различий между использованием ускорителя и использованием полного имени типа?
- Следует ли избегать использования полного имени типа всякий раз, когда акселератор доступен в качестве общей рекомендации?
- Как проверить, возможно, используя отражение, если ускоритель делает что-то другое, чем просто указание на базовый класс?
2 ответа
Глядя на статические методы:
PS C:\> [PSCustomObject] | gm -Static -MemberType Method
TypeName: System.Management.Automation.PSObject
Name MemberType Definition
---- ---------- ----------
AsPSObject Method static psobject AsPSObject(System.Object obj)
Equals Method static bool Equals(System.Object objA, System.Object objB)
new Method psobject new(), psobject new(System.Object obj)
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object o...
PS C:\> [System.Management.Automation.PSCustomObject] | gm -Static -MemberType Method
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method static bool Equals(System.Object objA, System.Object objB)
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object o...
Ускоритель типов добавил пару новых статических методов. Я подозреваю, что он использует один из них в качестве конструктора.
[PSObject] и [PSCustomObject] являются псевдонимами для одного и того же типа - System.Management.Automation.PSObject. Я не могу сказать, что есть веская причина для этого, но это, по крайней мере, наводит на мысль о двух разных целях, и, возможно, этого достаточно.
System.Management.Automation.PSObject используется для переноса объектов. Он был введен для обеспечения общего API отражения для любого объекта, который PowerShell оборачивает - .Net, WMI, COM, ADSI или простых пакетов свойств.
System.Management.Automation.PSCustomObject - это просто деталь реализации. Когда вы создаете объект PSObject, объект PSObject должен что-то перенести. Для пакетов свойств обернутый объект - это System.Management.Automation.PSCustomObject.SelfInstance (внутренний член). Этот экземпляр скрыт от обычного использования PowerShell, единственный способ наблюдать это с помощью отражения.
Пакеты свойств создаются в PowerShell несколькими способами:
$o1 = [pscustomobject]@{Prop1 = 42}
$o2 = new-object psobject -Property @{Prop1 = 42 }
И $o1, и $ o2 выше будут экземпляром PSObject, а PSObject будет оборачивать PSCustomObject.SelfInstance. PSCustomObject.SelfInstance используется внутри PowerShell для определения разницы между простой сумкой свойств и переносом любого другого объекта.