原谅标题,我不确定如何解释我所看到的.
示例代码:
$SampleValues = 1..5
$Result = "" | Select ID
$Results = @()
$SampleValues | %{
$Result.ID = $_
$Results += $Result
}
$Results
Run Code Online (Sandbox Code Playgroud)
这很简单:
预期结果是1,2,3,4,5,但运行时返回5,5,5,5,5
这是一个来自更复杂的脚本的准系统示例,我试图弄清楚为什么结果是这样的.在每次迭代中,已添加到$ Results的所有元素都将其值更新为最新值.我已经测试了强制所有内容到$ Script:或$ Global:scope并获得相同的结果.
我发现的唯一解决方案是将$ Result声明移动到循环中.
$SampleValues = 1..5
$Results = @()
$SampleValues | %{
$Result = "" | Select ID
$Result.ID = $_
$Results += $Result
}
Run Code Online (Sandbox Code Playgroud)
这有效(你得到1,2,3,4,5作为你的结果).它看起来像$ Results只是持有多个对单个$ Result对象的引用,但是为什么将它移动到循环中可以解决问题呢?在这个例子中,$ Result是一个字符串,所以也许每次迭代都会创建一个新对象,但即使我强制$ Result为一个整数(由于整数不像字符串那样不可变,因此不应该重新创建一个新对象)仍然解决了问题,我得到了我期望的结果.
如果有人对这个解决问题的确切原因有任何了解,我会非常好奇.我有很多替代方案可以实现,但没有明确理解为什么这种方式有效,这让我烦恼.
它通过进入循环来解决问题,因为那时你每次都创建一个新的$ Result对象,而不是在同一个上更改一个值(在数组中引用了5次).
它与您是否使用"" | Select ID或者123 | Select ID因为它只是PSCustomObject上的某种属性没有任何关系,PSCustomObject仍然是引用类型而不是值类型.
请记住,Powershell内部都是.NET.这里有一些C#类似于Powershell在你的第一个例子中所做的事情,它产生了所有5个(希望你知道C#):
var SampleValues = new []{1,2,3,4,5};
var Result = new CustomObject(){ ID = "" };
var Results = new List<Object>();
foreach (var _ in SampleValues) {
Result.ID = _;
Results.Add(Result);
}
Run Code Online (Sandbox Code Playgroud)
希望你可以看到移动var Result = new CustomObject(){ ID = "" }的内部foreach循环将使其更好地工作,并且同样的概念在PowerShell中也是如此.
| 归档时间: |
|
| 查看次数: |
3580 次 |
| 最近记录: |