入队后在队列中修改的C#队列对象
我有一个Queue<object>
,我将对象插入,但如果在将对象放入队列后修改对象,队列中的对象也会发生更改。入队后在队列中修改的C#队列对象
例如
object1 = 1;
queue.Enqueue(object1);
object1 = 0;
如果我然后去看看在排队,object1将等于0,没有1就像当我把它放在... 建议?
在C#中,除非另外指定,否则通常通过引用传递对象。您可以在将对象放入队列之前克隆对象,然后在更改原始副本时,队列中的内容将不会更改。
一个的许多方法来实现这一目标是做这样的事情:
object1 = 1;
queue.Enqueue(new Object(object1));
object1 = 0;
然后在对象的拷贝构造函数,做一名成员明智深副本:
class myClass
{
public int i;
public Object (Object object1)
{
this.i = object1.i;
}
}
您的队列是对象的引用队列,而不是对象的值。克隆对象并修改不在队列中工作的克隆对象,或者在将对象放入队列后不要修改对象。
考虑进一步解释的类比。想象一下,你必须跟踪100幅油画。您选择使用队列来跟踪所有的绘画。你有两个选择,以画保存在您的队列:
- 皮卡每个画作,并将其移动到队列
- 存储队列中的每一画的位置
好选项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
或者,你可以存储与值类型(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);
其他的答案是正确的在技术层面上,但我自问的是“为什么我要改变排队的对象?”。通常情况下,您将一些东西放在队列中,以便它可以进一步处理。如果你随后改变它,你发送的是什么行为?你究竟在做什么?原始对象或东西就像对象但不完全是什么?有什么区别,它们很重要?哪个版本是正确的?
你如何协调你所做的改变与队列另一端的结果?
如果你不能,那么你的过程是有缺陷的。如果可以的话,无论如何改变对象可能并不重要(不太可能是这种情况)。
对我来说,好像你可能在队列上有太多的东西,而你的对象需要分解和/或处理问题。
所有非常好的答案,在搜索了一下之后,似乎使用复制构造函数是最简单的方法来解决此问题,现在一切似乎都正常。看到这篇文章:https://stackoverflow.com/a/78577/1174574
想法?
似乎合理。两者都是相似的。两者都有小的折衷。只要你正确地克隆你的物体,并清楚地表明你是制作深层还是浅层复制品,就应该是好的。 –
看到我的“答案”。现在你知道如何,确保你应该。 – LoztInSpace
我需要做什么才能在我的对象上获得.Clone()属性? (自定义对象)包含一个引用? –
实施IClonable是不好的做法。这个问题解释了原因。 http://stackoverflow.com/questions/3712449/what-is-the-use-of-iclonable-interface-in-net。 –
@that_guy阅读我修改后的答案。 [Object.MemberwiseClone](http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx)方法也会返回浅拷贝,您需要深度复制。 –