2013-05-17 3 views
1

У меня есть Queue<object>, что я вставляю объекты, но если я изменю объект после того, как поместил его в очередь, объект в очереди также изменится.Объекты очереди C#, измененные в очереди после того, как они были установлены в очередь

Например

object1 = 1; 
queue.Enqueue(object1); 
object1 = 0; 

Если я затем смотреть в очереди, object1 будет равна 0, а не 1, как, когда я положил его в ... предложения?

ответ

1

В C# объекты, как правило, передаются по ссылкам, если не указано иное. Вы можете клонировать объекты перед тем, как поместить их в очередь, а затем, когда вы измените исходную копию, те, которые находятся в очереди, не будут изменены.

Один из многих способов для достижения этой цели делают что-то вроде этого:

object1 = 1; 
queue.Enqueue(new Object(object1)); 
object1 = 0; 

Затем в конструкторе копирования объекта, сделать член мудрой глубокой копию:

class myClass 
{ 
    public int i; 
    public Object (Object object1) 
    { 
     this.i = object1.i; 
    } 
} 
+0

Что мне нужно сделать, чтобы получить свойство .Clone() на моем объекте? (пользовательский объект) включают ссылку? –

+0

Плохая практика для внедрения IClonable. Этот вопрос объясняет, почему. http://stackoverflow.com/questions/3712449/what-is-the-use-of-iclonable-interface-in-net. –

+0

@that_guy прочитал мой измененный ответ. [Object.MemberwiseClone] (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx) Метод возвращает также мелкую копию, вам нужна глубокая копия. –

2

Ваша очередь представляет собой очередь ссылок на объекты, а не значения объекта. Либо клонировать объект и модифицировать клонированный объект, когда он не работает в очереди, либо не изменять объект после помещения его в очередь.

Рассмотрите аналогию для дальнейшего объяснения. Представьте, что вам нужно отслеживать 100 картин. Вы выбираете использовать очередь для отслеживания всех картин. У вас есть два варианта для хранения картин в очереди:

  1. Pickup каждый картину и переместить его в очередь
  2. магазина расположение каждой картины в очереди

вариант Ну-трудно потому что картины тяжелые действительно большие. Вариант 2 намного проще, потому что все, что вам нужно, - это простая ссылка на каждую картину. Однако, с вариантом 2, любой может изменить картину, не пройдя очередь, потому что картина фактически не находится в очереди. Вариант 1 называется pass by value. Вариант 2 называется pass by reference. И именно так C# хранит объекты в очереди.

Примечание: эта аналогия несовершенна, но она должна помочь вам понять, что происходит.

Следующий код должен помочь решить проблему:

object1 = 1; 
queue.Enqueue(object1); 
//Clone is a method you'll need to create on the class 
//C# provides a MemberwiseClone method that should be very helpful 
object2 = object1.Clone(); 
object2 = 2 

MemberwiseClone

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

int a = 1; 
var myQueue = new Queue<int>(); 
myQueue.Enqueue(a); 
a = 2; 
//Prints 1 
Console.WriteLine(myQueue.First()); 
//Prints 2 
Console.WriteLine(a); 
2

Других ответы правильны в техническом смысле, но я спрашиваю себя: «Почему я сначала меняю объекты в очереди?». Как правило, вы помещаете что-то в очередь, чтобы оно переместилось в другое место для дальнейшей обработки. Если вы впоследствии измените его, то какие действия вы отправляете и на чем вы работаете? Что-то, что является исходным объектом или чем-то вроде объекта, но не совсем? Каковы различия и важны ли они?Какая правильная копия/версия?

Как вы согласовываете сделанные вами изменения с результатами на другой стороне очереди?

Если вы не можете, значит, ваш процесс испорчен. Если вы можете тогда, то, вероятно, не имеет значения, измените ли вы объект в любом случае (вряд ли это так).

Кажется, что у вас может быть слишком много в очереди, и ваш объект нуждается в разрушении и/или в проблеме процесса.

0

Все действительно хорошие ответы, после поиска понемногу кажется, что использование конструктора копирования - это самый простой способ сделать это, и теперь все работает правильно. Пила на этом посту: https://stackoverflow.com/a/78577/1174574

Мысли?

+1

Кажется разумным. Оба они похожи. Оба имеют небольшие компромиссы. Вы должны быть хорошими, пока вы клонируете свои объекты правильно и четко показываете, делаете ли вы глубокую или мелкую копию. –

+0

См. Мой «ответ». Теперь вы знаете, как это сделать. – LoztInSpace

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