排队后在队列中修改的C#队列对象

时间:2013-05-17 05:02:49

标签: c# queue

我有一个Queue<object>我将对象推入,但是如果我在将对象放入队列后修改对象,队列中的对象也会发生变化。

例如

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

如果我再去查看队列,那么object1将等于0,而不是像我把它放入时那样... 建议?

4 个答案:

答案 0 :(得分:2)

您的队列是对象的引用队列,而不是对象的值。克隆对象并在不在队列中工作时修改克隆对象,或者在将对象放入队列后不修改对象。

考虑进一步解释的类比。想象一下,你必须跟踪100幅画作。您选择使用队列来跟踪所有绘画。您可以通过两种方式将绘画存储在队列中:

  1. 拿起每幅画并将其移入队列
  2. 将每幅画作的位置存储在队列中
  3. 选择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,char,bool,struct等)存储信息。值类型存储在具有选项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);
    

答案 1 :(得分:2)

其他答案在技术意义上是正确的,但我要问自己的是“为什么我首先要改变排队的对象?”。通常,您将某些东西放在队列中,以便它进入其他地方进行进一步处理。如果您随后更改了它,您发送的是什么以及您实际使用的是什么?某些东西是原始物体还是像物体一样但不完全?有什么区别,它们很重要吗?哪个是正确的副本/版本?

如何协调您对队列另一侧的结果所做的更改?

如果你不能,那么你的过程是有缺陷的。如果可以,那么无论如何你改变对象可能都没关系(不太可能)。

在我看来,你可能在队列上有太多的东西,你的对象需要分解和/或处理问题。

答案 2 :(得分:1)

在C#中,除非另有说明,否则对象通常通过引用传递。您可以在将对象放入队列之前克隆对象,然后在更改原始副本时,队列中的对象将不会更改。

实现这一目标的众多方法之一是做这样的事情:

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

然后在对象的复制构造函数中,执行成员明智的深层复制:

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

答案 3 :(得分:0)

所有非常好的答案,在搜索了一下后,似乎使用复制构造函数是最简单的方法,现在一切似乎都正常工作。看到这篇文章:https://stackoverflow.com/a/78577/1174574

思想?