我有一个变量,可以通过从其他变量更新值来更改其值。
我正在尝试创建自己的对象,并尝试了一些我在网上找到的代码,但我偶然发现了这个问题,无法确定如何发生。
准备工作
$a = "" | select First,Last #This just creates a custom object with two columns.
$b = @() #This is just an empty array to fill later on with the values of '$A'
$a.first = "Alpha"
$a.last = "Bravo"
$b += $a
$a.first = "Charlie"
$a.last = "Delta"
$b += $a
应该发生什么:
First Last ----- ---- Alpha Bravo Charlie Delta
但是实际结果是:
First Last ----- ---- Charlie Delta Charlie Delta
这是怎么了?
答案 0 :(得分:2)
Lee_Dailey指出,您要将引用添加到存储在{{中的自定义对象([pscustomobject]
[1] )实例中1}}数组$a
(假设$b
是引用类型),并且您要更新相同的自定义对象,因此最终得到:>
最直接的解决方法是在分配新的属性值之前创建[pscustomobject]
的副本,这可以通过$a
完成,这将创建一个浅表克隆:
.psobject.Copy()
当然,您可以避免此问题,而改用自定义对象 literals (PSv3 +),它每次都会创建一个新实例:
...
# Create a copy of $a to create the next array element.
$a = $a.psobject.Copy()
$a.first = "Charlie"
$a.last = "Delta"
$b += $a
顺便说一句:用$b = @()
$b += [pscustomobject] @{
first = "Alpha"
last = "Bravo"
}
$b += [pscustomobject] @{
first = "Charlie"
last = "Delta"
}
增长数组效率低下,因为每次都必须在幕后创建一个新数组;仅通过几次加法/迭代就可能不会引起注意,但是如果使用更大的数字,最好使用+=
之类的列表数据类型:
[System.Collections.Generic.List[object]]
$b = New-Object System.Collections.Generic.List[object]
$b.Add([pscustomobject] @{
first = "Alpha"
last = "Bravo"
})
$b.Add([pscustomobject] @{
first = "Charlie"
last = "Delta"
})
(实际上与[pscustomobject]
相同)是PowerShell的“属性包”类型,它允许您构造对象 ad ,而无需使用不同的.NET类型。提前宣布;从.NET的角度来看,给定的自定义对象的类型始终为[psobject]
,尽管特定的,动态附加的属性在设计上可能有所不同。
System.Management.Automation.PSCustomObject
(Select-Object
)也输出select
实例,尽管它们通过PowerShell的ETS (Extended Type System)报告自定义类型名称作为其主要类型名称:
[pscustomobject]
上述创建自定义对象的方法已经过时 ,而PSv3 +支持直接构建的文字PS> ("" | select First,Last).pstypenames
Selected.System.String # custom type name to reflect the type of the *input*
System.Management.Automation.PSCustomObject # the true type name
System.Object # the name of the base type
语法,这具有能够 initialize < / em>这些属性作为同一语句的一部分,并且比[pscustomobject] @{ ... }
(以及Select-Object
)还快{em> :
New-Object
注意:在PSv2中,您可以使用# PSv3+ equivalent of the above
# (except for the custom 'Selected.System.String' type name),
# allowing you to also initialize the properties.
[pscustomobject] @{
First = $null
Last = $null
}
来达到类似的效果,但是附加属性的顺序通常不会反映定义顺序。
请注意,您也始终可以在PowerShell中使用New-Object
cmdlet或在PSv5 +中,也可以使用语法New-Object PSCustomObject -Property @{ ... }
实例化常规.NET类型。
您可以使用相同的方法实例化用[<type>]::new([...])
关键字声明的PSv5+ custom classes。