我有一個Queue<object>
,我將對象插入,但如果在將對象放入隊列後修改對象,隊列中的對象也會發生更改。入隊後在隊列中修改的C#隊列對象
例如
object1 = 1;
queue.Enqueue(object1);
object1 = 0;
如果我然後去看看在排隊,object1將等於0,沒有1就像當我把它放在... 建議?
我有一個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)方法也會返回淺拷貝,您需要深度複製。 –