about_PSCustomObject

简短说明

介绍了 [psobject][pscustomobject] 类型加速器之间的差异。

长说明

[pscustomobject] 类型加速器是在 PowerShell 3.0 中添加的。

在添加此类型加速器之前,创建具有成员属性和值的对象比较复杂。 最初,必须使用 New-Object 来创建对象并使用 Add-Member 来添加属性。 例如:

PS> $object1 = New-Object -TypeName PSObject
PS> Add-Member -InputObject $object1 -MemberType NoteProperty -Name one -Value 1
PS> Add-Member -InputObject $object1 -MemberType NoteProperty -Name two -Value 2
PS> $object1 | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
one         NoteProperty int one=1
two         NoteProperty int two=2

PS> $object1

one two
--- ---
  1   2

后来,可以使用 New-ObjectProperty 参数传递包含成员和值的哈希表。 例如:

PS> $object2 = New-Object -TypeName PSObject -Property @{one=1; two=2}
PS> $object2 | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
one         NoteProperty int one=1
two         NoteProperty int two=2

PS> $object2

one two
--- ---
  1   2

从 PowerShell 3.0 开始,将哈希表强制转换为 [pscustomobject] 可实现相同的结果。

PS> $object3 = [pscustomobject]@{one=1; two=2}
PS> $object3 | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
one         NoteProperty int one=1
two         NoteProperty int two=2

PS> $object3

one two
--- ---
  1   2

PSObject 类型对象按照成员添加到对象的顺序维护其成员列表。 尽管哈希表对象不能保证键值对的顺序,但将文本哈希表强制转换为 [pscustomobject] 可保持该顺序。

哈希表必须是文本。 如果将哈希表括在括号中,或者强制转换包含哈希表的变量,则不能保证顺序被保留。

$hash = @{
    Name      = "Server30"
    System    = "Server Core"
    PSVersion = "4.0"
}
$Asset = [pscustomobject]$hash
$Asset
System      Name     PSVersion
------      ----     ---------
Server Core Server30 4.0

了解类型加速器

[psobject][pscustomobject] 是类型加速器。

有关详细信息,请参阅 about_Type_Accelerators

尽管你可能认为 [pscustomobject] 应该映射到 System.Management.Automation.PSCustomObject,但这两个类型不同。

PS> [pscustomobject] -eq [System.Management.Automation.PSCustomObject]
False

这两个类型加速器都映射到同一个类,即 PSObject

PS> [pscustomobject]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     PSObject                                 System.Object

PS> [psobject]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     PSObject                                 System.Object

[pscustomobject] 类型加速器添加到 PowerShell 时,它包含了额外的代码来处理哈希表PSObject 类型的转换。 仅当创建新对象时,才会调用此额外代码。 因此,不能将 [pscustomobject] 用于类型强制转换或类型比较,因为所有对象都被视为 PSObject 类型。

例如,使用 -is 运算符检查 cmdlet 返回的对象是否为 [pscustomobject] 与将其与 [psobject] 进行比较相同。

PS> (Get-Item /) -is [pscustomobject]
True

PS> (Get-Item /) -is [psobject]
True

将任何对象强制转换为 [psobject] 将获得原始对象的类型。 因此,将除哈希表以外的任何内容强制转换为 [pscustomobject] 会导致同一类型。

PS> ([psobject]@{Property = 'Value'}).GetType().FullName
System.Collections.Hashtable

PS> ([pscustomobject]123).GetType().Name
Int32

PS> ([pscustomobject]@{Property = 'Value'}).GetType().FullName
System.Management.Automation.PSCustomObject

虽然将对象强制转换为 [psobject] 似乎对类型没有影响,但 PowerShell 会在对象周围添加一个不可见的 [psobject] 包装器。 这会产生微小的副作用。

  • 被包装的对象将匹配其原始类型和 [psobject] 类型。

    PS> 1 -is [Int32]
    True
    PS> 1 -is [psobject]
    False
    PS> ([psobject] 1) -is [Int32]
    True
    PS> ([psobject] 1) -is [psobject]
    True
    
  • 格式运算符 (-f) 无法识别由 [psobject] 包装的数组。

    PS> '{0} {1}' -f (1, 2)
    1 2
    PS> '{0} {1}' -f ([psobject] (1, 2))
    Error formatting a string: Index (zero based) must be greater than or equal
    to zero and less than the size of the argument list..
    

说明

在 Windows PowerShell 中,通过将 Hashtable 强制转换为 [pscustomobject] 创建的对象没有 LengthCount 属性。 尝试访问这些成员将返回 $null

例如:

PS> $object = [PSCustomObject]@{key = 'value'}
PS> $object

key
---
value

PS> $object.Count
PS> $object.Length

从 PowerShell 6 开始,通过将 Hashtable 强制转换为 [pscustomobject] 创建的对象的 LengthCount 属性始终有一个值:1

另请参阅