Ускорители типа 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 класс - это должно означать, что использование ускорителей может сделать кучу других вещей, а не просто сделать код короче.

Мои вопросы по этому вопросу:

  1. У вас есть интересные примеры различий между использованием ускорителя и использованием полного имени типа?
  2. Следует ли избегать использования полного имени типа всякий раз, когда акселератор доступен в качестве общей рекомендации?
  3. Как проверить, возможно, используя отражение, если ускоритель делает что-то другое, чем просто указание на базовый класс?

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 для определения разницы между простой сумкой свойств и переносом любого другого объекта.

Другие вопросы по тегам