在C#中的foreach循环中更新结构

时间:2009-10-23 10:29:56

标签: c# .net foreach

我有这段代码(C#):

using System.Collections.Generic;

namespace ConsoleApplication1
{
    public struct Thing
    {
        public string Name;
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Thing> things = new List<Thing>();
            foreach (Thing t in things) //  for each file
            {
                t.Name = "xxx";
            }
        }
    }
}

不会编译 错误是:

Cannot modify members of 't' because it is a 'foreach iteration variable'

但是,如果我将Thing更改为class而不是struct,则会进行编译。

请有人解释发生了什么事吗?

4 个答案:

答案 0 :(得分:9)

或多或少的说法,编译器不会让你在foreach中更改(部分)循环var。

只需使用:

for(int i = 0; i < things.Count; i+= 1) //  for each file
{
    things[i].Name = "xxx";
}

Thing是一个类时它起作用,因为你的循环var是一个引用,你只对引用的对象进行更改,而不是对引用本身进行更改。

答案 1 :(得分:7)

struct不是引用类型,而是值类型。

如果对classstruct而不是Thing,则foreach循环会为您创建一个引用变量,它会指向您列表中的正确元素。但由于它是一个值类型,它只能在Thing的副本上运行,在这种情况下是迭代变量。

答案 2 :(得分:2)

结构是值类型,但类是引用类型。这就是为什么它编译时这是一个类而不是它是一个结构

查看更多:http://www.albahari.com/valuevsreftypes.aspx

答案 3 :(得分:1)

我更喜欢@Henk的解决方案的替代语法就是这个。

DateTime[] dates = new DateTime[10];

foreach(int index in Enumerable.Range(0, dates.Length))
{
   ref DateTime date = ref dates[index];

   // Do stuff with date.
   // ...
}

如果你在循环中做了大量合理的工作,那么无需在任何地方重复索引就更容易了。

P.S。 DateTime实际上是一个非常糟糕的例子,因为它没有你可以设置的任何属性,但你得到了图片。