Вопрос

У меня есть этот код (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 к a class вместо того, чтобы struct, однако, он компилируется.

Пожалуйста, кто-нибудь может объяснить, что происходит?

Это было полезно?

Решение

Более или менее то, что он говорит, компилятор не позволит вам изменить (части) циклического var в foreach.

Просто используйте:

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

И это работает, когда Thing является классом, потому что тогда ваш зацикленный var является ссылкой, а вы вносите изменения только в объект, на который есть ссылка, а не в саму ссылку.

Другие советы

Структура - это не ссылочный тип, а тип значения.

Если бы у вас класс для Thing был class , цикл foreach создал бы для вас ссылочную переменную, что бы укажите на правильный элемент в вашем списке. Но поскольку это тип значения, он работает только с копией вашего Thing , который в данном случае является итерационной переменной.

Структура - это тип значения, а класс - это ссылочный тип. Вот почему он компилируется, когда это класс, но не когда это структура

Подробнее: http://www.albahari.com/valuevsreftypes.aspx

Альтернативный синтаксис, который я предпочитаю решению @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.
   // ...
}

Если вы выполняете разумный объем работы в цикле, то отсутствие необходимости повторять индексацию везде проще на глаз, imo.

P.S.DateTime на самом деле является действительно плохим примером, поскольку у него нет никаких свойств, которые вы могли бы установить, но вы получаете картинку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top