Powershell PSObject、哈希表和PSCustomObject之间的差异

Powershell PSObject、哈希表和PSCustomObject之间的差异,powershell,powershell-3.0,psobject,Powershell,Powershell 3.0,Psobject,有人能解释一下细节吗?如果我使用 $var = [PSObject]@{a=1;b=2;c=3} 然后我使用getType()PowerShell查找它的类型,PowerShell告诉我它属于哈希表类型 当使用(别名gm)检查对象时,很明显已经创建了哈希表,因为它具有键和值属性。那么,“普通”哈希表有什么区别呢 另外,使用PSCustomObject有什么好处?当用这样的东西创建一个 $var = [PSCustomObject]@{a=1;b=2;c=3} 对我来说唯一可见的区别是PSCu

有人能解释一下细节吗?如果我使用

$var = [PSObject]@{a=1;b=2;c=3}
然后我使用
getType()
PowerShell查找它的类型,PowerShell告诉我它属于哈希表类型

当使用(别名
gm
)检查对象时,很明显已经创建了哈希表,因为它具有
属性。那么,“普通”哈希表有什么区别呢

另外,使用PSCustomObject有什么好处?当用这样的东西创建一个

$var = [PSCustomObject]@{a=1;b=2;c=3}
对我来说唯一可见的区别是PSCustomObject的不同数据类型。另外,使用
gm
进行检查,发现现在每个键都已添加为NoteProperty对象,而不是键和值属性


但是我有什么优势呢?我可以使用它的键访问我的值,就像在哈希表中一样。我可以在PSCustomObject中存储多个简单的键值对(例如键对象对),就像在哈希表中一样。那么优势是什么呢?有什么重要的区别吗?

我认为你将看到的最大区别是性能。看看这篇博文:

作者运行了以下代码:

$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
@{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
#>
博客作者的输出:

TotalSeconds
------------
 167.8825285
   0.7459279
他对代码结果的评论如下:

当你把它们放在一起时,你可以看到速度上的差异。在我的计算机上,object方法需要167秒,而hash table方法需要不到一秒的时间来构建哈希表,然后进行查找

以下是一些其他更微妙的好处:

我认为PSObject的一个优点是可以使用它创建自定义方法

比如说,

$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()

您可以使用它来控制PSObject属性的排序顺序(请参见)

当您需要它们的集合时,可以使用
[PSCustomObject]
而不是
哈希表。以下是说明如何处理这些问题的区别:

$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
格式表
将为
$Hash
产生以下结果:

Name    Value
----    -----
Name    Object 1
Squared 1
Index   1
Name    Object 2
Squared 4
Index   2
Name    Object 3
Squared 9
...
以及
$CustomObject
的以下内容:

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

同样的事情发生在导出Csv时,因此使用
[PSCustomObject]
而不仅仅是普通的
哈希表的原因是我想创建一个文件夹。如果我使用PSObject,你可以通过
看看它

PS>[PSObject]@{Path='foo';Type='directory'}
名称值
----                           -----
路富
类型目录
但是PSCustomObject看起来正确

PS>[PSCustomObject]@{Path='foo';Type='directory'}
路径类型
----                                    ----
foo目录
然后我可以用管道输送这个物体

[PSCustomObject]@{Path='foo';Type='directory'}新项

包装对象,以提供可用成员的备选视图以及扩展这些成员的方法。成员可以是方法、属性、参数化属性等

换句话说,
PSObject
是一个对象,您可以在创建它之后向其添加方法和属性

:

哈希表,也称为字典或关联数组,是一种紧凑的数据结构,存储一个或多个键/值对

哈希表经常被使用,因为它们对于查找和检索数据非常有效

您可以像使用哈希表一样使用
PSObject
,因为PowerShell允许您向
PSObjects
添加属性,但您不应该这样做,因为您将无法访问
哈希表
的特定功能,例如
属性。此外,可能会有性能成本和额外的内存使用

:

当使用PSObject的构造函数(不带参数)时,用作占位符BaseObject

这对我来说并不清楚,但从中似乎更清楚:

[PSCustomObject]是类型加速器。它构造一个PSObject,但这样做的方式会导致哈希表键成为属性。PSCustomObject本身不是对象类型–它是一个流程快捷方式。。。PSCustomObject是在没有构造函数参数的情况下调用PSObject时使用的占位符

关于您的代码,
@{a=1;b=2;c=3}
是一个
哈希表
[PSObject]@{a=1;b=2;c=3}
不会将
哈希表
转换为
PSObject
或生成错误。对象仍然是一个
哈希表
。但是,
[PSCustomObject]@{a=1;b=2;c=3}
哈希表
转换为
PSObject
。我找不到说明为什么会发生这种情况的文档

如果要将
哈希表
转换为对象,以便将其键用作属性名,可以使用以下代码行之一:

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

# OR

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

# NOTE: Both have the type PSCustomObject
如果要将多个
哈希表
转换为其键为属性名的对象,可以使用以下代码:

$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
@{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
#>
@{name='a';num=1},@{name='b';num=2}|
%{[PSCustomObject]$\
#或
@{name='a';num=1},@{name='b';num=2}|
%{新对象PSObject-属性$}
很难找到有关
NoteProperty
的文档,除了
NoteProperty
之外,没有任何
-MemberType对添加对象属性有意义。Windows PowerShell Cookbook(第三版)将
Noteproperty
Membertype定义为:

由您提供的初始值定义的特性

  • Lee,H.(2013)。Windows PowerShell食谱。奥莱利传媒有限公司。895

我们的Windows PKI中有一堆模板,我们需要一个脚本,它必须与所有活动模板一起工作。我们不需要它