| description | Explains the differences between the [psobject] and [pscustomobject] type accelerators. |
|---|---|
| Locale | en-US |
| ms.date | 07/02/2024 |
| online version | https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_pscustomobject?view=powershell-5.1&WT.mc_id=ps-gethelp |
| schema | 2.0.0 |
| title | about_PSCustomObject |
Explains the differences between the [psobject] and [pscustomobject] type
accelerators.
The [pscustomobject] type accelerator was added in PowerShell 3.0.
Prior to adding this type accelerator, creating an object with member
properties and values was more complicated. Originally, you had to use
New-Object to create the object and Add-Member to add properties. For
example:
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 2Later, you could use the Property parameter of New-Object to pass a
Hashtable containing the members and values. For example:
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 2Since PowerShell 3.0, casting a Hashtable to [pscustomobject] achieves
the same result.
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 2PSObject type objects maintain the list of members in the order that the
members were added to the object. Even though Hashtable objects don't
guarantee the order of the key-value pairs, casting a literal hashtable to
[pscustomobject] maintains the order.
The hashtable must be a literal. If you wrap the hashtable in parentheses or if you cast a variable containing a hashtable, there is no guarantee that the order is preserved.
$hash = @{
Name = "Server30"
System = "Server Core"
PSVersion = "4.0"
}
$Asset = [pscustomobject]$hash
$AssetPSVersion Name System
--------- ---- ------
4.0 Server30 Server Core
[psobject] and [pscustomobject] are type accelerators.
For more information, see about_Type_Accelerators.
Even though you might think that [pscustomobject] should map to
System.Management.Automation.PSCustomObject, the types are different.
PS> [pscustomobject] -eq [System.Management.Automation.PSCustomObject]
FalseBoth type accelerators are mapped to the same class, PSObject:
PS> [pscustomobject]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True PSObject System.Object
PS> [psobject]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True PSObject System.ObjectWhen the [pscustomobject] type accelerator was added to PowerShell, it
included extra code to handle conversion of a Hashtable to a PSObject
type. This extra code is only invoked when a new object is being created.
Therefore, you can't use [pscustomobject] for type coercion or type
comparison, because all objects are treated as PSObject types.
For example, using the -is operator to check that an object returned by a
cmdlet is a [pscustomobject] is the same as comparing it to [psobject].
PS> (Get-Item /) -is [pscustomobject]
True
PS> (Get-Item /) -is [psobject]
TrueWhen you cast any object to [psobject] you get the type of the original
object. Therefore, casting anything other than a Hashtable to
[pscustomobject] results in the same type.
PS> ([psobject]@{Property = 'Value'}).GetType().FullName
System.Collections.Hashtable
PS> ([pscustomobject]123).GetType().Name
Int32
PS> ([pscustomobject]@{Property = 'Value'}).GetType().FullName
System.Management.Automation.PSCustomObjectWhile, casting an object to [psobject] appears to have no affect on the type,
PowerShell adds an invisible [psobject] wrapper around the object. This can
have subtle side effects.
-
Wrapped objects match their original type and the
[psobject]type.PS> 1 -is [int32] True PS> 1 -is [psobject] False PS> ([psobject] 1) -is [int32] True PS> ([psobject] 1) -is [psobject] True
-
The format operator (
-f) doesn't recognized an array wrapped by[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..
Case-sensitive dictionaries might contain key names that only differ by case.
When you cast such a dictionary to a [pscustomobject], PowerShell preserves
that case of the keys but isn't case-sensitive. As a result:
- The case of the first duplicate key becomes the name of that key.
- The value of the last case-variant key becomes the property value.
The following example demonstrates this behavior:
$OrderedHashTable = [System.Collections.Specialized.OrderedDictionary]::new()
$OrderedHashTable['One'] = 1
$OrderedHashTable['TWO'] = 2
$OrderedHashTable['two'] = 3 # case variation
$OrderedHashTable['Three'] = 3
$OrderedHashTableNotice that the ordered hashtable contains multiple keys that differ only by case.
Name Value
---- -----
One 1
TWO 2
two 3
Three 3
When that hashtable is cast to a [pscustomobject], the case of the name of
first key is used, but that value of the last matching key name is used.
[pscustomobject]$OrderedHashTableOne TWO Three
--- --- -----
1 3 3
In Windows PowerShell, objects created by casting a Hashtable to
[pscustomobject] don't have the Length or Count properties.
Attempting to access these members returns $null.
For example:
PS> $object = [pscustomobject]@{key = 'value'}
PS> $object
key
---
value
PS> $object.Count
PS> $object.LengthStarting in PowerShell 6, objects created by casting a Hashtable to
[pscustomobject] always have a value of 1 for the Length and Count
properties.
- about_Object_Creation
- about_Objects
- System.Management.Automation.PSObject
- System.Management.Automation.PSCustomObject