Не может изменить объект структуры в цикле - PullRequest
2 голосов
/ 28 января 2010

У меня есть список структуры. В цикле я пытаюсь изменить свойство объекта, что происходит, но когда я (Быстрый просмотр в Visual Studio) изучаю объект списка, новое значение не отражается. это из-за того, что объект структуры не может быть изменен, когда в коллекции? Я использую список дженериков со структурой в качестве типа в списке

Ответы [ 4 ]

2 голосов
/ 28 января 2010

Вы упоминаете «изменить свойство объекта» в контексте структуры, но важно, что структура не является объектом . Другие люди ответили на вопрос о копируемых структурах (и об отмене изменений), но для решения этой проблемы real здесь у вас есть изменяемая (изменяемая) структура 1007 * на всех . Если вы не используете XNA (или аналогичную программу), в этом просто нет необходимости.

Если вы хотите изменить свойства, сделайте его классом:

public class Foo {
    public string Bar {get;set;}
}

Теперь это ссылочный тип, и ваши изменения (obj.Bar = "abc";) будут сохраняться через foreach. Если вы действительно хотите / нуждаетесь в структуре, сделайте ее неизменной:

public struct Foo {
    private readonly string bar;
    public string Bar { get {return bar; }}
    public Foo(string bar) {this.bar = bar;}
}

Теперь вы не можете совершить ошибку, изменив значение копии; вместо этого вам придется использовать индексатор для swap значения (list[i] = new Foo("abc");). Более подробный (и вы не можете использовать foreach), но правильный.

Но ИМО, используй класс. Структуры довольно редки, если честно. Если вы не уверены: класс.

1 голос
/ 28 января 2010

Я думаю, я знаю, в чем может быть проблема.

struct Astruct
{
   int amember;
}

List < Astruct > listofStructs;

foreach(Astruct A in listofStructs)
{
     A.amember = 1337;
}

если это то, что вы делаете ...

когда вы используете структуры в c #, на них не ссылаются, а копируют! это означает, что содержимое вашего списка копируется в A, поэтому при изменении A оно не меняет значение в списке!

для решения этой проблемы (если это ваша проблема ...) либо используйте CLASSES, а не STRUCTS, таким образом A будет ссылкой, ИЛИ вместо этого используйте ручную итерацию для цикла, то есть:

for(int i=0;i < listofStructs.Count;i++)
{
    listofStructs[i].amember = 1337;
}

в качестве альтернативы, если вы используете список, возможно, вам следует использовать итератор или что-то в этом роде ... но вышеприведенное обязательно должно решить эту проблему.

1 голос
/ 28 января 2010

Если вы используете цикл foreach, вы, вероятно, получили

Ошибка компилятора CS1654

Сообщение об ошибке не может изменить членов переменная, потому что это только для чтения тип переменной '

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

Одна общая область, в которой это происходит, в циклах foreach. Это ошибка времени компиляции для изменения значения элементов коллекции. Следовательно, Вы не можете вносить какие-либо изменения в элементы, которые являются типами значений, включая структуры.

Однако вы можете попробовать

struct MyStruct
{
    public int i;
}

List<MyStruct> list = new List<MyStruct> 
        { new MyStruct { i = 1 }, new MyStruct { i = 2 } };

for(int i = 0; i < list.Count; i++)
{
    MyStruct val = list[i];
    val.i++;
    list[i] = val;
}

EDIT

См. Также Учебное пособие по структурам

Структуры против классов

Структуры могут показаться похожими на классы, но есть важные различия что вы должны знать. Первый из все, классы являются ссылочными типами и структуры являются типами значений.

0 голосов
/ 28 января 2010

Учитывая информацию в вашем посте (хотя мне бы хотелось увидеть сам код), позвольте мне выдвинуть наиболее вероятную проблему и ее решение.

   foreach(var s in listOfStructs)
    {
      s.Property = x;
    }

s назначается копии фактической структуры в коллекции. s.set_Property теперь изменяет копию, которая выбрасывается в конце текущей итерации.

Это потому, что 2 переменные типа значения не могут указывать на один и тот же экземпляр.

struct1 = new MyStruct(100, 200);
struct2 = struct1;   // struct2 is now a copy of struct1

Теперь к вопросу о том, как изменить экземпляры в коллекции:
Получить объект для изменения в локальной переменной (копия создана). Изменить это. Теперь удалите оригинальный объект и вставьте копию. используйте listOfStructs[i] = modifiedInstance.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...