次の方法で共有


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-Object パラメーターを使用して、メンバーと値を含む Hashtable を渡すことができます。 次に例を示します。

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 以降、 Hashtable[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 型オブジェクトは、メンバーがオブジェクトに追加された順序でメンバーのリストを保持します。 Hashtableオブジェクトはキーと値のペアの順序を保証しませんが、リテラルハッシュテーブルをキャストして[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 に追加されると、Hashtable から PSObject 型への変換を処理する追加のコードが含まれていました。 この追加のコードは、新しいオブジェクトが作成されている場合にのみ呼び出されます。 したがって、すべてのオブジェクトが [pscustomobject] 型として扱われるため、型強制型比較または型比較にを使用することはできません。

たとえば、 -is 演算子を使用して、コマンドレットによって返されるオブジェクトが [pscustomobject] であることを確認することは、 [psobject]と比較する場合と同じです。

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

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

オブジェクトを [psobject] にキャストすると、元のオブジェクトの型が取得されます。 そのため、 Hashtable 以外をキャストして [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 はオブジェクトの周囲に invisible[psobject] ラッパーを追加します。 これにより、微妙な副作用が発生する可能性があります。

  • ラップされたオブジェクトは、元の型と [psobject] 型と一致します。

    PS> 1 -is [int32]
    True
    PS> 1 -is [psobject]
    False
    PS> ([psobject] 1) -is [int32]
    True
    PS> ([psobject] 1) -is [psobject]
    True
    
  • format 演算子 (-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..
    

類似のキーを含むハッシュテーブルの変換

大文字と小文字を区別するディクショナリには、大文字と小文字のみが異なるキー名が含まれている場合があります。 このようなディクショナリを [pscustomobject]にキャストすると、PowerShell ではキーの大文字と小文字が保持されますが、大文字と小文字は区別されません。 その結果、次のような影響が出ています。

  • 最初の重複キーの大文字と小文字は、そのキーの名前になります。
  • 最後の case-variant キーの値がプロパティ値になります。

この動作の例を次に示します。

$Json = '{
  "One": 1,
  "two": 2,
  "Two": 3,
  "three": 3,
  "Three": 4,
  "THREE": 5
}'
$OrderedHashTable = $Json | ConvertFrom-Json -AsHashTable
$OrderedHashTable

順序付けられたハッシュテーブルには、大文字と小文字のみが異なる複数のキーが含まれていることに注意してください。

Name                           Value
----                           -----
One                            1
two                            2
Two                            3
three                          3
Three                          4
THREE                          5

そのハッシュテーブルが [pscustomobject]にキャストされると、最初のキーの名前の大文字と小文字が使用されますが、最後に一致するキー名の値が使用されます。

[pscustomobject]$OrderedHashTable
One two three
--- --- -----
  1   3     5

メモ

Windows PowerShell では、 Hashtable をキャストして作成されたオブジェクト [pscustomobject]Length または Count プロパティがありません。 これらのメンバーにアクセスしようとすると、 $nullが返されます。

次に例を示します。

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

key
---
value

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

PowerShell 6 以降では、[pscustomobject] をキャストして作成されたオブジェクトには、常に 1 プロパティと Count プロパティの値がされます。

関連項目