C# List 賦值(一) --引用類型的賦值和複製

最近項目維護中遇到一個問題,確切的說應該是兩個月前的問題也是由於這裏引發的,惋惜當時困於業務不熟悉,也沒有更多時間容許查詢根源,致使再次引起了新的問題!!!html

問題場景:基礎數據存於List類型的BOMs中,計算過程是對List類型的normalBoms和configBoms變量傳值後,normalBoms和configBoms進行計算,發現學習

對configBoms的操做會修改基礎數據BOMs中的值!!!
spa

起初就考慮到是由於List類型是引用類型,因此傳值會修改原值,可是normalBoms的值沒有同步被修改,因此詳細比較兩個變量的傳值邏輯:.net

 

 1        static List<int> BOMs = new List<int>();  2 static void Main(string[] args)  3  {  4 for (int i = 0; i < 10; i++)  5  {  6  BOMs.Add(i);  7  }  8  9 List<int> normalBoms = null; 10 List<int> configBoms = null; 11 12 normalBoms = GetNormalBoms(); 13 configBoms = GetConfigBoms(); 14 15 configBoms[9] = 19; 16 17  } 18 static List<int> GetNormalBoms() 19  { 20 List<int> boms = new List<int>(); 21 //... 22 foreach (int bom in boms) 23  { 24 //... 25  boms.Add(bom); 26  } 27 //...... 28 return boms; 29  } 30 31 static List<int> GetConfigBoms() 32  { 33 List<int> boms = null; 34 //...... 35 boms = BOMs; 36 //...... 37 return boms; 38 }

 注意:GetNormalBoms()方法中行22和方法GetConfigBoms()方法中行35的差別,因此猜想(由於沒有認真考慮)是沒有進行new操做(new會分配新的內存),最終致使configBoms仍是隻想BOMs的同一個內存,即發放返回了一個引用,後續對configBoms的操做也會影響BOMs,做出相應修改:code

行10List<int> configBoms = null; 修改成 List<int> configBoms = new List<int>(); ,(分配了內存,configBoms是指向新的內存的)orm

最終運行,發現後續對configBoms的操做仍是會影響BOMs,更加詳細的思考爲何???htm

這裏就開始認真回想以前對引用類型的理解,由於常有查看值類型和引用類型的區別,如今是理論和實踐的結合了:對象

首先,理解引用類型的變量存儲的是內存的地址(對象的引用),即對象的數據在託管堆中,變量中的引用在棧上(借鑑:http://www.cnblogs.com/anding/p/5229756.htmlblog

其次,引用類型的變量賦值傳遞的是對象的應用,也就是變量賦值的是內存的地址,因此賦值後多個變量指向了同一個對象實例內存

基於以上兩點,代碼中問題不難解釋了:雖然configBoms經過new操做分配了新的內存(此時新分配的內存記爲mom1,原來BOMs指向的內存mom0),可是後續的賦值操做configBoms=GetConfigBoms()中沒有修改內存指向,因此賦值操做是變量configBoms的值,即configBoms中的地址不在指向mom1,而是指向了mom0,此時的configBoms是mom0存儲的對象實例的一個引用,和BOMs等同,因此修改configBoms會影響BOMs。(:內存mom1並無消失,只是configBoms不在指向mom1,也不能經過configBoms修改mom1的內容)

可是反觀方法GetNormalBoms()方法,方法中先經過new分配了行的內存(記爲mom2),而後爲新的變臉賦值是經過Add方法,是在新的內存mom2中增長數據,變量中的地址沒有變,因此normalBoms變量仍是指向mom2的,與configBoms和BOMs不一樣。

瞭解了原理,那麼解決個人問題的方法就是:在給configBoms傳值時,不能只修改變量值,而是要分配新內存,數據要賦值進新內存中

List的複製(借鑑:https://blog.csdn.net/chrean/article/details/5686998

由於考慮到實際項目中,不是循環都合適,同時現有代碼結構不易修改,不經過相似GetNormalBoms()的方法給configBoms賦值,經過new List<int>(BOMs)進行賦值,即:

行13修改成 configBoms = new List<int>(GetConfigBoms()); 

問題最終是解決了。因此學以至用,細緻入微,真的是很基礎的內容,之前只知道概念,如今真正纔是開始將學習的知識運用到實踐中來。

相關文章
相關標籤/搜索