powershell - create - Diferencia entre PSObject, Hashtable y PSCustomObject
create object powershell (5)
Creo que la mayor diferencia que verás es el rendimiento. Echa un vistazo a esta entrada de blog:
Combinar objetos de manera eficiente: use una tabla de hash para indexar una colección de objetos
El autor ejecutó el siguiente código:
$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
#>
Su comentario sobre los resultados del código es:
Puedes ver la diferencia en la velocidad cuando lo pones todo junto. El método de objeto tarda 167 segundos en mi computadora, mientras que el método de tabla hash tardará menos de un segundo en construir la tabla hash y luego hacer la búsqueda.
Éstos son algunos de los otros beneficios más sutiles: la visualización predeterminada de objetos personalizados en PowerShell 3.0
¿Alguien puede explicar los detalles? Si creo un objeto usando
$var = [PSObject]@{a=1;b=2;c=3}
y luego busco su tipo usando getType()
PowerShell me dice que es de tipo Hashtable .
Cuando se usa Get-Member (alias gm
) para inspeccionar el objeto, es obvio que se ha creado una tabla hash, ya que tiene una keys
y una propiedad de values
. Entonces, ¿cuál es la diferencia a una tabla hash "normal"?
Además, ¿cuál es la ventaja de usar un PSCustomObject? Al crear uno usando algo como esto
$var = [PSCustomObject]@{a=1;b=2;c=3}
La única diferencia visible para mí es el tipo de datos diferente de PSCustomObject . Además, en lugar de las propiedades de claves y valores, una inspección con gm
muestra que ahora todas las claves se han agregado como un objeto NoteProperty.
¿Pero qué ventajas tengo? Puedo acceder a mis valores utilizando sus claves, como en la tabla hash. Puedo almacenar más que simples pares clave-valor (pares clave-objeto, por ejemplo) en el objeto PSCustomObject, SOLO como en la tabla hash. Entonces, ¿cuál es la ventaja? ¿Hay diferencias importantes?
Digamos que quiero crear una carpeta. Si uso un objeto PSO, puedes ver que está mal si lo miras
PS > [PSObject] @{Path=''foo''; Type=''directory''}
Name Value
---- -----
Path foo
Type directory
Sin embargo el PSCustomObject parece correcto
PS > [PSCustomObject] @{Path=''foo''; Type=''directory''}
Path Type
---- ----
foo directory
Entonces puedo canalizar el objeto
[PSCustomObject] @{Path=''foo''; Type=''directory''} | New-Item
Un escenario donde se usa [PSCustomObject]
lugar de HashTable
es cuando necesitas una colección de ellos. Lo siguiente es ilustrar la diferencia en cómo se manejan:
$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
resultará en lo siguiente para $Hash
:
Name Value
---- -----
Name Object 1
Squared 1
Index 1
Name Object 2
Squared 4
Index 2
Name Object 3
Squared 9
...
Y lo siguiente para $CustomObject
:
Name Index Squared
---- ----- -------
Object 1 1 1
Object 2 2 4
Object 3 3 9
Object 4 4 16
Object 5 5 25
...
Lo mismo sucede con Export-Csv
, por lo tanto, la razón para usar [PSCustomObject]
lugar de solo HashTable
.
Una ventaja que creo que para PSObject es que puede crear métodos personalizados con él.
Por ejemplo,
$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()
Puede usar esto para controlar el orden de clasificación de las propiedades de PSObject (vea Clasificación de PSObject )
De la documentación de PSObject
:
Envuelve un objeto que proporciona vistas alternativas de los miembros disponibles y formas de ampliarlos. Los miembros pueden ser métodos, propiedades, propiedades parametrizadas, etc.
En otras palabras, un objeto PSObject
es un objeto al que puede agregar métodos y propiedades después de haberlo creado.
De la documentación de "About Hash Tables" :
Una tabla hash, también conocida como diccionario o matriz asociativa, es una estructura de datos compacta que almacena uno o más pares clave / valor.
...
Las tablas hash se usan con frecuencia porque son muy eficientes para encontrar y recuperar datos.
Puede usar un PSObject
como un Hashtable
porque PowerShell le permite agregar propiedades a PSObjects
, pero no debe hacer esto porque perderá el acceso a la funcionalidad específica de Hashtable
, como las propiedades Keys
y Values
. Además, puede haber costos de rendimiento y uso de memoria adicional.
La documentación de PowerShell tiene la siguiente información sobre PSCustomObject
:
Sirve como un marcador de posición BaseObject cuando se usa el constructor de PSObject sin parámetros.
Esto no me quedó claro, pero parece más claro un post en un foro de PowerShell del coautor de varios libros de PowerShell :
[PSCustomObject] es un acelerador de tipos. Construye un objeto PSO, pero lo hace de una manera que hace que las claves de tabla hash se conviertan en propiedades. PSCustomObject no es un tipo de objeto per se, es un método abreviado de proceso. ... PSCustomObject es un marcador de posición que se usa cuando se llama a PSObject sin parámetros de constructor.
Con respecto a su código, @{a=1;b=2;c=3}
es un Hashtable
. [PSObject]@{a=1;b=2;c=3}
no convierte el Hashtable
en un PSObject
o genera un error. El objeto sigue siendo un Hashtable
. Sin embargo, [PSCustomObject]@{a=1;b=2;c=3}
convierte el Hashtable
en un PSObject
. No pude encontrar documentación que indique por qué sucede esto.
Si desea convertir un Hashtable
en un objeto para usar sus claves como nombres de propiedades, puede usar una de las siguientes líneas de código:
[PSCustomObject]@{a=1;b=2;c=3}
New-Object PSObject -Property @{a=1;b=2;c=3}
# NOTE: Both have the type PSCustomObject
Si desea convertir un número de Hashtables
en un objeto donde sus claves son nombres de propiedades, puede usar el siguiente código:
@{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
#>
Encontrar documentación sobre la NoteProperty
fue difícil. En la documentación de Add-Member
, no hay ningún tipo de -MemberType
que tenga sentido para agregar propiedades de objetos que no sean NoteProperty
. El libro de cocina de Windows PowerShell (3ª edición) definió el tipo de Noteproperty
Noteproperty como:
Una propiedad definida por el valor inicial que usted proporciona
- Lee, H. (2013). Libro de cocina de Windows PowerShell . O''Reilly Media, Inc. p. 895.