簡単な説明
[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 プロパティの値がされます。
関連項目
PowerShell