PowerShell和C#的区别枚举集合时 [英] Differences Between PowerShell and C# when Enumerating a Collection

查看:127
本文介绍了PowerShell和C#的区别枚举集合时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是在C#一个简单的场景:

Here is a simple scenario in C#:

var intList = new List<int>();
intList.Add(4);
intList.Add(7);
intList.Add(2);
intList.Add(9);
intList.Add(6);

foreach (var num in intList)
{
  if (num == 9)
  {
    intList.Remove(num);
    Console.WriteLine("Removed item: " + num);
  }

  Console.WriteLine("Number is: " + num);
}

这将引发出现InvalidOperationException 因为我改变这个集合,而枚举它

This throws an InvalidOperationException because I am modifying the collection while enumerating it.

现在考虑类似的PowerShell代码:

Now consider similar PowerShell code:

$intList = 4, 7, 2, 9, 6

foreach ($num in $intList)
{
  if ($num -eq 9)
  {
    $intList = @($intList | Where-Object {$_ -ne $num})
    Write-Host "Removed item: " $num
  }

  Write-Host "Number is: " $num
}

Write-Host $intList

该脚本实际上从列表中移除9号!没有抛出异常。

This script actually removes the number 9 from the list! No exceptions thrown.

现在,我知道C#示例使用List对象,而PowerShell的示例使用数组,但如何PowerShell的枚举将在修改的集合循环?

Now, I know the C# example uses a List object while the PowerShell example uses an array, but how does PowerShell enumerate a collection that will be modified during the loop?

推荐答案

答案已经被@Sean给,我只是提供代码,这表明原来的集合在的foreach 没有改变:它枚举通过原始集合并没有矛盾,因此

The answer is already given by @Sean, I am just providing the code which shows that the original collection is not changed during foreach: it enumerates through the original collection and there is no contradiction therefore.

# original array
$intList = 4, 7, 2, 9, 6

# make another reference to be used for watching of $intList replacement
$anotherReferenceToOriginal = $intList

# prove this: it is not a copy, it is a reference to the original:
# change [0] in the original, see the change through its reference
$intList[0] = 5
$anotherReferenceToOriginal[0] # it is 5, not 4

# foreach internally calls GetEnumerator() on $intList once;
# this enumerator is for the array, not the variable $intList
foreach ($num in $intList)
{
    [object]::ReferenceEquals($anotherReferenceToOriginal, $intList)
    if ($num -eq 9)
    {
        # this creates another array and $intList after assignment just contains
        # a reference to this new array, the original is not changed, see later;
        # this does not affect the loop enumerator and its collection
        $intList = @($intList | Where-Object {$_ -ne $num})
        Write-Host "Removed item: " $num
        [object]::ReferenceEquals($anotherReferenceToOriginal, $intList)
    }

    Write-Host "Number is: " $num
}

# this is a new array, not the original
Write-Host $intList

# this is the original, it is not changed
Write-Host $anotherReferenceToOriginal

输出:

5
True
Number is:  5
True
Number is:  7
True
Number is:  2
True
Removed item:  9
False
Number is:  9
False
Number is:  6
5 7 2 6
5 7 2 9 6

我们可以看到, $ intList中当我们中删除项目被改变。它仅仅意味着该变量现在包含一个新的数组的引用,它的变量变了,不是数组。循环将继续是没有改变, $ anotherReferenceToOriginal 仍然包含对它的引用原始数组的枚举。

We can see that $intList is changed when we "remove an item". It only means that this variable now contains a reference to a new array, it is the variable changed, not the array. The loop continues enumeration of the original array which is not changed and $anotherReferenceToOriginal still contains a reference to it.

这篇关于PowerShell和C#的区别枚举集合时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆