C# List方法中存儲的問題


遇到一個bug,抓耳撓塞好久都沒有解決,有必要記錄一下。

現在我使用了一個多維list。

IList<IList<int>> list = new List<IList<int>>();

我在main函數中調用了方法函數,在方法函數中使用list.add()方法向list中添加sublist。添加代碼如下:

IList<int> l = new List<int>();
for(int i=0;i<10;i++)
{
    if (條件)
    {
        l.clear();
        list.Add(sublist);
    }
}

 

一共添加了3個元素

但是最終的list中,卻始終只有第三個sublist,前兩個sublist存在但是為空。這就非常奇怪,既然前兩個元素存在,那么就代表list.Add(sublist)語句成功運行了,但為什么值為空呢?

我第一時間就懷疑Add方法會覆蓋掉之前的值,於是我又在main函數中手動添加了兩個sublist,打印出來發現,后面添加的都能成功寫入,只有循環內的不可以。

這段代碼是在vscode里面寫的,由於不能單步調試查看局部變量,耽擱了好多時間。於是我把所有代碼移到了VS2017上,開始我的單步調試(VS2017大法好!)

我一步一步調試,發現第一個sublist寫入是成功的,到了第二個sublist要寫入的那一刻,刷!list[0]的值變成了空!

現在問題找到了,但是我不明白問題出在哪里。

在網上終於搜到了解決方法。原來是在循環中如果使用同一個sublist,那么每次add都會把之前覆蓋掉。解決辦法就是不要在循環外定義sublist,而是在循環內部定義。

該方法給出的解釋如下:

1.對於引用類型,在循環外new了 a 對象后,這個對象的引用地址就確定了,執行到第二次list.add()時,list[0]中保存的a對象和新加的list[1] a對象是同一個對象,使用的是同一個地址,也就是說在添加list[1]是,list[0]也被修改了,因為它倆指針指向同一個地址,同樣,后面添加的都會修改前面所有對象,結果就是list最后所有數據都是最后的list[end_num]。

2.string也是引用對象,有唯一的引用地址(假設分配的是address1),但當add list[1]的時候(str值改變時),.net會檢查內存,發現不等於之前的字符串(list[1]不等於list[0]),.net會給原來的str重新分配內存空間address2,存儲list[0],而list[1]使用原來的空間address1。這樣使得每次list.add時都不會覆蓋之前的元素,因為它們使用的是不同的地址空間。
————————————————
版權聲明:本文為CSDN博主「IT登山家」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_35409640/article/details/71404203

但是呢,我在進一步調試中發現兩個問題:

1.如果去除l.clear(),程序是正常的,list值全部正常,只有添加了l.clear(),list的前幾個值才會被抹去。

2.在main函數中加這樣的循環(包含l.Clear()),list可以正常寫入

結合該方法,我認為覆蓋的原因如下:

現在申請的所有類型在.net中都被認為是引用對象,當add的時候,.net會統一重新分配內存。但是在add之前,l都指向了l的地址,查了資料就知道,clear並不清除list內存,想必是只擦除了地址,所以才會既沒有報錯,也沒有值。

至於在main函數中為什么不會發生這種現象,我還沒有比較好的思路,可能是因為list是在main中一定,不需要引用函數,也就沒有list的引用過程,可能add方法就直接寫入list了。水平有限,歡迎有識之士補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM