Différence entre PSObject, Hashtable et PSCustomObject

quelqu'un Peut-il expliquer les détails? Si je crée un objet en utilisant

$var = [PSObject]@{a=1;b=2;c=3}

et puis je regarde pour son type à l'aide de getType() Powershell me dit que c'est de type Hashtable. Lorsqu'on utilise gm pour inspecter l'objet, il est évident qu'un hashtable a été créé, puisqu'il possède une propriété keys et values. Alors quelle est la différence avec un hashtable "normal"?

en outre, Quel est l'avantage d'utiliser un PSCustomObject? Quand on en crée un en utilisant quelque chose comme ça

$var = [PSCustomObject]@{a=1;b=2;c=3}

la seule différence visible, c'est le type de données différent de PSCustomObject. Aussi au lieu des clés et des propriétés de valeur, une inspection avec gm montre que maintenant chaque clé a été ajoutée comme objet NoteProperty. Mais quels sont mes avantages? Je peux accéder à mes valeurs en utilisant ses clés, comme dans le hashtable. Je peux stocker plus que de simples couples de valeurs de clé (par exemple des couples clé-objet) dans le PSCustomObject, tout comme dans le hashtable. Si quel est l'avantage? Existe-il des différences importantes?

18
demandé sur masi 2012-12-23 20:52:25

5 réponses

je pense que la plus grande différence que vous verrez est la performance. Jetez un oeil à ce blog:

http://powertoe.wordpress.com/2011/03/31/combining-objects-efficiently-use-a-hash-table-to-index-a-collection-of-objects/

L'auteur a couru le code suivant:

$numberofobjects = 1000

$objects = (0..$numberofobjects) |% {
    New-Object psobject -Property @{'Name'="object$_";'Path'="Path$_"}
}
$lookupobjects = (0..$numberofobjects) |% {
    New-Object psobject -Property @{'Path'="Path$_";'Share'="Share$_"}
}

$method1 = {
    foreach ($object in $objects) {
        $object |Add-Member NoteProperty -Name Share -Value ($lookupobjects|?{$_.Path -eq $object.Path} |select -First 1 -ExpandProperty share)
    }
}
Measure-Command $method1 |select totalseconds

$objects = (0..$numberofobjects) |% {
    New-Object psobject -Property @{'Name'="object$_";'Path'="Path$_"}
}
$lookupobjects = (0..$numberofobjects) |% {
    New-Object psobject -Property @{'Path'="Path$_";'Share'="Share$_"}
}

$method2 = {
    $hash = @{}
    foreach ($obj in $lookupobjects) {
        $hash.($obj.Path) = $obj.share
    }
    foreach ($object in $objects) {
        $object |Add-Member NoteProperty -Name Share -Value ($hash.($object.path)).share
    }
}
Measure-Command $method2 |select totalseconds

<#
Blog author's output:

TotalSeconds
------------
 167.8825285
   0.7459279
#>

son commentaire concernant les résultats du code est:

Vous pouvez voir la différence de vitesse quand vous mettez tout ensemble. La méthode objet prend 167 secondes sur mon ordinateur pendant que la méthode de table de hachage prendra moins d'une seconde pour construire la table de hachage et puis faire la recherche

voici quelques-uns des autres avantages, plus subtils: http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2012/04/13/Custom-objects-default-display-in-PowerShell-3-0.aspx

1
répondu Adam Driscoll 2018-05-07 05:59:40

Un scénario où [PSCustomObject] est utilisé au lieu de HashTable c'est quand vous avez besoin d'une collection d'entre eux. Voici pour illustrer la différence dans la façon dont ils sont traités :

$Hash   = 1..10 | %{ @{Name="Object $_" ; Index=$_ ; Squared = $_*$_} }
$Custom = 1..10 | %{[PSCustomObject] @{Name="Object $_" ; Index=$_ ; Squared = $_*$_} }

$Hash   | Format-Table -AutoSize
$Custom | Format-Table -AutoSize

$Hash   | Export-Csv .\Hash.csv -NoTypeInformation
$Custom | Export-Csv .\CustomObject.csv -NoTypeInformation

Format-Table sera $Hash:

Name    Value
----    -----
Name    Object 1
Squared 1
Index   1
Name    Object 2
Squared 4
Index   2
Name    Object 3
Squared 9
...

et les suivants pour $CustomObject:

Name      Index Squared
----      ----- -------
Object 1      1       1
Object 2      2       4
Object 3      3       9
Object 4      4      16
Object 5      5      25
...

la même chose se produit avec Export-Csv, donc la raison d'utiliser [PSCustomObject] au lieu de tout simplement HashTable

21
répondu tkokasih 2014-05-09 03:10:10

je veux créer un dossier. Si J'utilise un PSObject vous pouvez dire qu'il est faux par regarder

PS > [PSObject] @{Path='foo'; Type='directory'}

Name                           Value
----                           -----
Path                           foo
Type                           directory

Toutefois, le PSCustomObject semble correct

PS > [PSCustomObject] @{Path='foo'; Type='directory'}

Path                                    Type
----                                    ----
foo                                     directory

je peux alors Piper l'objet

[PSCustomObject] @{Path='foo'; Type='directory'} | New-Item
14
répondu Steven Penny 2014-11-11 18:01:55

un avantage que je pense pour psobject est que vous pouvez créer des méthodes personnalisées avec elle. Par exemple,

$o=New-Object PSObject -Property @{
   "value"=9
}
Add-Member -MemberType ScriptMethod -Name "Sqrt" -Value {
    echo "the square root of $($this.value) is $([Math]::Round([Math]::Sqrt($this.value),2))"
} -inputObject $o

$o.Sqrt()

vous pouvez l'utiliser pour contrôler l'ordre de tri de la psobject propriétés ( voir PSObject sorting )

11
répondu Loïc MICHEL 2017-05-23 11:54:39

PSObject documentation:

enveloppe un objet fournissant des vues alternatives des membres disponibles et des façons de les étendre. Les membres peuvent être des méthodes, propriétés, propriétés paramétrées, etc.

En d'autres termes, un PSObject est un objet auquel vous pouvez ajouter des méthodes et des propriétés après l'avoir créé.

à Partir de la "Sur les Tables de Hachage" de la documentation:

une table de hachage, aussi connue sous le nom de dictionnaire ou tableau associatif, est une structure de données compacte qui stocke une ou plusieurs paires clé/valeur.

...

les tables de hachage sont fréquemment utilisées parce qu'elles sont très efficaces pour trouver et extraire des données.

Vous pouvez utiliser un PSObject comme Hashtable parce que PowerShell vous permet d'ajouter des propriétés à PSObjects, mais vous ne devriez pas faire cela parce que vous perdrez l'accès à l' Hashtable spécifique fonctionnalités, telles que la Keys et Values propriétés. En outre, il peut y avoir des coûts de rendement et l'utilisation de mémoire supplémentaire.

la documentation PowerShell contient les informations suivantes sur PSCustomObject:

Sert de placeholder BaseObject lorsque le constructeur de PSObject sans paramètres est utilisé.

C'était pas clair pour moi, mais un post sur un PowerShell forumle co-auteur d'un nombre de livres PowerShell semble plus clair:

[PSCustomObject] est un accélérateur de type. Il construit un PSObject, mais le fait d'une manière qui résulte en des clés de table de hachage devenant des propriétés. PSCustomObject n'est pas un type d'objet en soi – c'est un raccourci de processus. ... PSCustomObject est un placeholder qui est utilisé lorsque PSObject est appelé sans paramètres de constructeur.

concernant votre code,@{a=1;b=2;c=3} est un Hashtable. [PSObject]@{a=1;b=2;c=3} ne pas convertir le HashtablePSObject ou générer une erreur. L'objet est un Hashtable. Cependant, [PSCustomObject]@{a=1;b=2;c=3} Converse le Hashtable dans un PSObject. Je n'ai pas pu trouver de documentation expliquant pourquoi cela se produit.

Si vous voulez convertir un Hashtable dans un objet afin d'utiliser ses clés comme noms de propriétés, Vous pouvez utiliser une des lignes de code suivantes:

[PSCustomObject]@{a=1;b=2;c=3}
New-Object PSObject -Property @{a=1;b=2;c=3}

# NOTE: Both have the type PSCustomObject

Si vous voulez convertir un certain nombre de Hashtables dans un objet dont les clés sont des noms de propriété vous pouvez utiliser le code suivant:

@{name='a';num=1},@{name='b';num=2} |
 % { [PSCustomObject]$_ }

# OR

@{name='a';num=1},@{name='b';num=2} |
 % { New-Object PSObject -Property $_ }

<#
Outputs:

name num
---- ---
a      1
b      2
#>

trouver la documentation concernant NoteProperty a été difficile. Dans le Add-Member documentation, il n'est pas tout -MemberType cela a du sens pour ajouter des propriétés d'objet autres que NoteProperty. Windows PowerShell livre de recettes (3e Édition) définit l' Noteproperty Membertype:

Une propriété définie par la valeur initiale que vous fournissez

  • Lee, H. (2013). Windows PowerShell Livre De Cuisine. O'Reilly Media, Inc. p. 395.
2
répondu Dave F 2018-05-06 12:24:17