代码之家  ›  专栏  ›  技术社区  ›  sharkin

foreach()是否按引用迭代?

  •  63
  • sharkin  · 技术社区  · 16 年前

    考虑一下:

    List<MyClass> obj_list = get_the_list();
    foreach( MyClass obj in obj_list )
    {
        obj.property = 42;
    }
    

    “obj”是否是对列表中相应对象的引用,以便当我更改属性时,一旦在某个地方构造了对象实例,更改将一直存在于该对象实例中?

    10 回复  |  直到 16 年前
        1
  •  59
  •   Brian Rasmussen    16 年前

    对, obj 是对集合中当前对象的引用(假定 MyClass 实际上是一个类)。如果您通过引用更改了任何属性,那么您将像预期的那样更改对象。

    但是请注意,您不能更改变量 OBJ 它本身就是迭代变量。如果你尝试,你会得到一个编译错误。这意味着您不能使其为空,如果您正在迭代值类型,则不能修改任何成员,因为这样会更改值。

    C语言规范规定(8.8.4)

    “迭代变量对应于 一个只读局部变量 扩展到嵌入的 声明。

        2
  •  22
  •   jaccso    13 年前

    是的,直到将泛型类型从List更改为IEnumerable。

        3
  •  19
  •   JaredPar    16 年前

    你在这里问了两个不同的问题,让我们按顺序回答。

    foreach循环是否按引用迭代?

    如果你的意思是和引用循环相同的C++一样,那么,没有C C没有与C++相同的本地变量引用,因此不支持这种类型的迭代。

    改变会持续吗

    假设myClass是引用类型,则答案是yes。类是.NET中的引用类型,因此迭代变量是对一个变量的引用,而不是对副本的引用。对于值类型,这不是真的。

        4
  •  15
  •   Community Mohan Dere    11 年前

    嗯,当我遍历var集合时,我的更改没有在foreach循环中更新:

    var players = this.GetAllPlayers();
    foreach (Player player in players)
    {
        player.Position = 1;
    }
    

    当我将var更改为list时,它开始工作。

        5
  •  6
  •   helencrump TheRustling    10 年前

    在这种情况下(使用 List<T> )但是如果要在泛型 IEnumerable<T> 然后它就依赖于它的实现。

    如果它仍然是 列表& T; T[] 例如,所有这些都将按预期工作。 当你和一个 IEnumerable<t> 那是用产量建造的。在这种情况下,不能再修改的属性 T 在一个迭代中,如果您重复相同的内容,则期望它们出现。 IEnumerable<t> 再一次。

        6
  •  3
  •   Deepfreezed    15 年前

    这是真的,只要它不是一个结构。

        7
  •  2
  •   Charles Bretana    16 年前

    好吧,在不理解“引用迭代”的确切含义的情况下,我不能明确回答“是”或“否”,但我可以说,表面上的情况是,.NET框架正在为每次客户端代码调用for each时构建一个“枚举器”类,在for each的生命周期内,它将引用指针维护到正在迭代集合,每次foreach迭代时,ir“传递”一个项并“递增”枚举器中指向下一个项的指针或引用…

    无论您正在迭代的集合中的项是值类型还是引用类型,都会发生这种情况。

        8
  •  2
  •   Wolf    7 年前

    也许通过版本C 7.3,您会感兴趣,如果枚举器 电流 属性返回引用类型。以下内容有效(MS文档中的逐字副本):

    Span<int> storage = stackalloc int[10];
    int num = 0;
    foreach (ref int item in storage)
    {
        item = num++;
    }
    

    有关此新功能的详细信息,请访问 C# foreach statement | Microsoft Docs .

        9
  •  0
  •   Stan R.    16 年前

    obj是对列表中某个项的引用,因此,如果更改它的值,它将保持不变。 现在,您应该关注的是get_The_List()是否对列表进行深度复制或返回相同的实例。

        10
  •  0
  •   Brian Scott    16 年前

    是的,这也是您不能在foreach语句的上下文中更改可枚举对象的原因。