原谅标题,我真的不知道如何解释我所看到的。
示例代码:
$SampleValues = 1..5
$Result = "" | Select ID
$Results = @()
$SampleValues | %{
$Result.ID = $_
$Results += $Result
}
$Results
这很简单:
- 创建一个包含 5 个数字的数组以用于循环
- 使用名为 ID 的 NoteProperty 创建一个临时变量
- 创建一个空数组来存储结果
- 遍历 5 个数字中的每一个,将它们分配给一个临时变量,然后将其附加到一个数组中。
预期结果是 1,2,3,4,5,但运行时返回 5,5,5,5,5
这是一个从更复杂的脚本中提取的准系统示例,我试图弄清楚为什么结果会是这样。在每次迭代中,所有已添加到 $Results 的元素都将其值更新为最新值。我已经测试了将所有内容强制到 $Script: 或 $Global: 范围并获得相同的结果。
我找到的唯一解决方案如下,它将 $Result 声明移动到循环中。
$SampleValues = 1..5
$Results = @()
$SampleValues | %{
$Result = "" | Select ID
$Result.ID = $_
$Results += $Result
}
这有效(您的结果为 1,2,3,4,5)。看起来 $Results 只是持有对单个 $Result 对象的多个引用,但为什么将它移到循环中可以解决问题?在这个例子中 $Result 是一个字符串,所以它可能会在每次迭代时创建一个新对象,但即使我强制 $Result 是一个整数(它不应该重新创建一个新对象,因为整数不像字符串那样不可变)它仍然解决了问题,我得到了我预期的结果。
如果有人对这解决问题的确切原因有任何见解,我很好奇。有很多替代方案可供我实现,但不具体理解为什么这种方式会困扰我。
最佳答案
它通过进入循环来解决问题,因为这样您每次都创建一个新的 $Result 对象,而不是更改同一个对象的值(在数组中引用了 5 次)。
与是否使用""| 没有任何关系选择 ID
或 123 |选择 ID
,因为它只是 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);
}
希望您可以看到在 foreach
循环中移动 var Result = new CustomObject(){ ID = ""}
会使其更好地工作,并且是相同的概念在 Powershell 中也是如此。
关于循环中的 Powershell 值失去其值(value),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6230838/