变量更改值而无需重新分配

时间:2019-04-30 21:56:24

标签: powershell

我有一个变量,可以通过从其他变量更新值来更改其值。

我正在尝试创建自己的对象,并尝试了一些我在网上找到的代码,但我偶然发现了这个问题,无法确定如何发生。

准备工作

$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

这是怎么了?

1 个答案:

答案 0 :(得分:2)

Lee_Dailey指出,您要将引用添加到存储在{{中的自定义对象([pscustomobject] [1] )实例中1}}数组$a(假设$b引用类型),并且您要更新相同的自定义对象,因此最终得到:

  • 2个指向同一对象的数组元素...
  • ...其属性值是您最后分配的属性。

最直接的解决方法是在分配新的属性值之前创建[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]]

[1] PowerShell中的自定义对象:

$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.PSCustomObjectSelect-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