2013-05-17 77 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. 皮卡每个画作,并将其移动到队列
  2. 存储队列中的每一画的位置

好选项1是难因为画很重很大。选项2要容易得多,因为您需要的只是每幅油画的简单参考。但是,对于选项2,任何人都可以在不通过队列的情况下更改绘画,因为绘画实际上并不在队列中。选项1被称为按值传递。选项2称为通过引用。这就是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

或者,你可以存储与值类型(int,焦炭,BOOL,结构等)的信息,如果你是存储简单和小的信息。值类型存储在带有选项1的队列中(按值传递)

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