2016-11-19 77 views
5

當我想在c#中執行一些操作時,有一點問題。我會給你一個小例子。當推送列表被清除時,通用列表的堆棧被清除

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>(); 
List<HufmannLetter> letterList = new List<HufmannLetter>();  

while(true){ 

    letterList.Add("asd"); 
    letterList.Add("sad"); 

    steps.Push(letterList); 
    letterlist.Clear();  
} 

在這段代碼中,我想將鏈表推送到堆棧,而不是刪除列表中的所有項目。當我清除列表時,我的堆棧的第一個索引消失,因爲它通過引用傳遞。我錯了嗎?因爲我不知道它爲什麼會發生。

所以我使用傳值方法。

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>(); 
List<HufmannLetter> letterList = new List<HufmannLetter>(); 

while(true) { 

    letterList.Add("asd"); 
    letterList.Add("sad"); 

    List<HufmannLetter> tempLetterList = new List<HufmannLetter>(letterList); 
    steps.Push(tempLetterList); 
    letterlist.Clear();  
} 

這是解決問題的好方法嗎?這樣它工作,但可讀性下降。你建議我什麼?

謝謝...

+2

「我錯了嗎?」是的,在你展示的代碼中沒有傳遞參考。你可以通過缺少'ref'和'out'來判斷。我建議你閱讀http://jonskeet.uk/csharp/parameters.html和http://jonskeet.uk/csharp/references.html請注意,按值傳遞引用與傳遞引用不同。 –

回答

3

只需創建循環內一個新的List<HufmannLetter>對象,並添加到堆棧中。重用相同的列表對象不會有任何性能優勢。

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>(); 

while(true) 
{ 
    List<HufmannLetter> letterList = new List<HufmannLetter>(); 

    letterList.Add("asd"); 
    letterList.Add("sad"); 

    steps.push(letterList); 
} 
+0

是的,我知道,它不影響我的表現,但我正在考慮我的代碼的可理解性。但如果沒有任何方法,我不會改變我的代碼。非常感謝:) – Berkin

+1

沒有任何答案解釋OP的'當我清除列表時,我的堆棧的第一個索引消失,因爲它通過引用傳遞。我錯了嗎?因爲我不知道爲什麼會發生。「 –

+0

@柏金,你是什麼意思_「沒有任何辦法」_?我的例子與你的不一樣。 –

1

您可以創建new List<HufmannLetter>()並在構造函數給前面的列表,這將創造出將不會被清除新的對象。

while(condition) 
{ 
    letterList.Add("asd"); 
    letterList.Add("sad"); 

    steps.push(new List<HufmannLetter>(letterList)); 
    letterlist.Clear(); 
} 

編輯

所以List<T>是引用類型,你是把在棧中letterList。通過這種方式,您可以將項目中的參考List<T>的值轉移。所以你的letterList變量引用與棧中的項目相同的對象。當您清除letterList中的項目時,它們也會在堆棧的項目中清除。

檢查什麼是Reference Types

+1

沒有任何答案解釋OP的'當我清除列表時,我的堆棧的第一個索引消失,因爲它通過引用傳遞。我錯了嗎?因爲我不知道爲什麼會發生。「 –

+0

@Am_I_Helpful我認爲該操作理解爲什麼值從堆棧中的列表中清除。如果他不明白,我會寫一點解釋。 – mybirthname

-1

你也可以做,因爲

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>(); 

while(true) 
{ 
var tempList = new List<HufmannLetter>; 
tempList.add("asd"); 
steps.push(tempList); 
} 

,或者你可以試試這個

steps.push(tempList.ToList()); 
    tempList.Clear(); 
+0

這與在6分鐘前給出的botond.botos的答案相同。 – mybirthname

+0

是的,但請檢查第二部分 –

1

List<>是一個可變引用類型。

當您將List<>傳遞給某個方法時,您會通過的副本。所以你只是告訴它是哪一個List<>。這不會複製(克隆)List<>的全部內容。

當你把(Push)一List<>Stack<>,什麼Stack<>真正保持一個參考的副本的List<>此實例。如果稍後對該實例進行了修改,例如使用.Add("asd").Clear(),則可以看到是否遵循Stack<>保留的引用或您擁有的其他引用從局部變量引用的此「突變」。 這兩個引用都指向List<>的同一個實例。

時,在你的代碼,你說:

letterList.Clear(); // do not change reference, follow reference and mutate the instance it refers to 

將修改(變異)的List<>現有實例,使其成爲空。任何人都可以看到這個變化,參考這個特定的List<>實例。

相反,如果你做了:

letterList = new List<string>(); // create new instance, change reference to point there (reference assignment), old instance is unchanged 

,將有「感動」的letterList參考指向的List<>一個實例。這不會影響其他引用「舊」實例的人。


標題引用傳遞用法是一種誤導。它應該是引用類型和傳遞引用或類似的東西。