2009-10-23 1 views
7

У меня есть этот код (C#):Update Struct в Еогеасп цикл в 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, однако, это не компилируется.

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

+0

Связанный вопрос http://stackoverflow.com/questions/1538301/c-does-foreach-iterate-by-reference/1538316#1538316 –

+0

Спасибо за ссылку, Брайан. –

ответ

9

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

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

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

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

+0

Именно то, что я искал! спасибо, Хенк :) –

7

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

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

+0

Да, это актуально. Поскольку это тип значения, вся структура является переменной цикла, и поэтому ее часть не может быть изменена. –

+0

Спасибо за объяснение differene, Johannes. Очень признателен. +1 –

2

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

Смотреть еще: http://www.albahari.com/valuevsreftypes.aspx

1

Альтернативный синтаксис, который я предпочитаю @ решение Хенк является это.

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 - действительно очень плохой пример, поскольку у него нет никаких свойств, которые вы можете установить, но вы получаете изображение.

Смежные вопросы