about_PSCustomObject

Brève description

Explique les différences entre les accélérateurs de type [psobject] et [pscustomobject].

Description longue

L’accélérateur de type [pscustomobject] a été ajouté dans PowerShell 3.0.

Avant d’ajouter cet accélérateur de type, la création d’un objet avec des propriétés de membre et des valeurs était plus complexe. À l’origine, vous devez utiliser New-Object pour créer l’objet et Add-Member pour ajouter des propriétés. Par exemple:

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

Plus tard, vous pouvez utiliser le paramètre Property de New-Object pour passer un hashtable contenant les membres et les valeurs. Par exemple:

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

Depuis PowerShell 3.0, la conversion d’une table de hachage pour [pscustomobject] obtient le même résultat.

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 objets de type conservent la liste des membres dans l’ordre dans lequel les membres ont été ajoutés à l’objet. Même si table de hachage objets ne garantissent pas l’ordre des paires clé-valeur, la conversion d’une table de hachage littérale sur [pscustomobject] conserve l’ordre.

La table de hachage doit être un littéral. Si vous encapsulez la table de hachage entre parenthèses ou si vous cassez une variable contenant une table de hachage, il n’existe aucune garantie que l’ordre est conservé.

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

Présentation des accélérateurs de type

[psobject] et [pscustomobject] sont des accélérateurs de type.

Pour plus d’informations, consultez about_Type_Accelerators.

Même si vous pensez que [pscustomobject] doit être mappé à System.Management.Automation.PSCustomObject, les types sont différents.

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

Les deux accélérateurs de type sont mappés à la même classe, PSObject:

PS> [pscustomobject]

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

PS> [psobject]

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

Lorsque l’accélérateur de type [pscustomobject] a été ajouté à PowerShell, il incluait du code supplémentaire pour gérer la conversion d’un de table de hachage en type PSObject. Ce code supplémentaire est appelé uniquement lorsqu’un nouvel objet est créé. Par conséquent, vous ne pouvez pas utiliser [pscustomobject] pour la contrainte de type ou la comparaison de types, car tous les objets sont traités comme types PSObject.

Par exemple, l’utilisation de l’opérateur -is pour vérifier qu’un objet retourné par une applet de commande est un [pscustomobject] est identique à la comparaison avec [psobject].

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

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

Lorsque vous castez un objet sur [psobject] vous obtenez le type de l’objet d’origine. Par conséquent, le cast n’importe quoi autre qu’une table de hachage pour [pscustomobject] entraîne le même 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.PSCustomObject

Bien que le cast d’un objet sur [psobject] n’ait aucun impact sur le type, PowerShell ajoute un wrapper invisible[psobject] autour de l’objet. Cela peut avoir des effets secondaires subtils.

  • Les objets encapsulés correspondent à leur type d’origine et au type [psobject].

    PS> 1 -is [int32]
    True
    PS> 1 -is [psobject]
    False
    PS> ([psobject] 1) -is [int32]
    True
    PS> ([psobject] 1) -is [psobject]
    True
    
  • L’opérateur de format (-f) n’a pas reconnu de tableau encapsulé par [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..
    

Conversion de tables de hachage contenant des clés similaires

Les dictionnaires respectant la casse peuvent contenir des noms de clés qui diffèrent uniquement par cas. Lorsque vous castez un tel dictionnaire dans un [pscustomobject], PowerShell conserve ce cas des clés, mais n’est pas sensible à la casse. Par conséquent :

  • Le cas de la première clé en double devient le nom de cette clé.
  • La valeur de la dernière clé case-variant devient la valeur de propriété.

L’exemple suivant illustre ce comportement :

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

Notez que la table de hachage ordonnée contient plusieurs clés qui diffèrent uniquement par cas.

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

Lorsque cette table de hachage est convertie en [pscustomobject], le cas du nom de la première clé est utilisé, mais cette valeur du nom de la clé correspondante est utilisée.

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

Remarques

Dans Windows PowerShell, les objets créés en cas de conversion d’un de table de hachage sur [pscustomobject] n’ont pas les propriétés Length ou Count. La tentative d’accès à ces membres retourne $null.

Par exemple:

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

key
---
value

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

À compter de PowerShell 6, les objets créés en cas de conversion d’un de table de hachage sur [pscustomobject] ont toujours une valeur de 1 pour les propriétés longueur et Count.

Voir aussi