我有一个变量,可以通过我从其他变量更新值来更改其值。
我正在尝试创建自己的对象,并正在尝试在网上找到的一些代码,但我偶然发现了这个问题,无法将我的头缠住。
准备:
$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
应该发生的事情:
第一个------ ------Alpha Bravo查理三角洲
,但实际结果是:
第一个------ ------查理三角洲查理三角洲
这里有什么问题?
正如Lee_dailey指出的那样,您将参考添加到自定义对象([pscustomobject]
[1] (实例中存储在$a
中数组$b
(鉴于[pscustomobject]
是A 参考类型(,并且您正在更新相同的自定义对象,因此您最终出现了:
- 2个数组元素指向同一对象...
- ...其属性值是您分配的最后一个值。
最直接的修复是在分配新属性值之前创建$a
的A copy ,可以用.psobject.Copy()
来完成,该值可以创建一个 - 浅 - 克隆:
...
# Create a copy of $a to create the next array element.
$a = $a.psobject.Copy()
$a.first = "Charlie"
$a.last = "Delta"
$b += $a
当然,您可以避免问题并使用custom-object 文字(psv3 (,这每次都会创建一个新实例:
$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"
})
[1] PowerShell中的自定义对象:
[pscustomobject]
(实际上与[psobject]
相同(是PowerShell的"属性袋"类型,它允许您构建对象 adhoc 而无需提前声明的不同的.NET类型;从.NET的角度来看,给定的自定义对象的类型始终是System.Management.Automation.PSCustomObject
,尽管特定的,动态附加的属性可以通过设计而有所不同。
Select-Object
(select
(也输出[pscustomobject]
实例,尽管它们通过PowerShell的ETS(扩展类型系统(报告了自定义类型名称,作为其主要类型名称:
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
创建自定义对象的上述方法是过时的,但是PSV3 支持直接构造的字面 [pscustomobject] @{ ... }
语法,这具有能够初始化的附加优势。属性作为同一语句的一部分,并且比Select-Object
快(以及New-Object
(:
# 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
}
注意:在PSV2中,您可以使用New-Object PSCustomObject -Property @{ ... }
来相似效果,但是附加属性的顺序通常不会反映定义顺序。
请注意,您始终可以使用New-Object
cmdlet或在PSV5 中实例化PowerShell的常规.NET类型,或者使用语法[<type>]::new([...])
进行实例化。您使用相同的方法来实例化PSV5 用class
关键字声明的自定义类。