在研究前輩們寫的代碼,總是搞不明白。word文中引文的索引和引文列表中的索引對應關系是什么呢?是如何對應上的?我冥思苦想,昨天又系統地看了下代碼,才所有悟,所以記錄下我的探索過程。
如下圖所示:
圖1
圖2
圖1,是word文中引文,圖2是題錄引文列表,紅色的是索引,這兩個索引是要一一對應的。
這段代碼實現的功能:過濾掉bib_List的重復項,然后初始化內存題錄表。
1 //bib_List 是題錄列表,Globals.BibTableAccessor._dictBibs是內存題錄列表字典,用來存儲word文檔的題錄列表。 2 for (int i = 0; i < bib_List.Count; i++) 3 { 4 if (!bib.Contains(bib_List[i])) 5 { 6 bib.Add(bib_List[i]); 7 } 8 } 9 Globals.BibTableAccessor._dictBibs[Globals.MemoryDataKey] = bib;
1 Int32 i_BIndex=1; 2 for (int i = 0; i < bib_List.Count; i++) 3 { 4 //初始化格式化內存表記錄 5 MemoryData memData = new MemoryData(); 6 memData.BPhysicsID = i_BIndex; 7 if (existBibs.ContainsKey(bib_List[i].BibliographyId)) 8 { 9 //若有重復處理 10 } 11 else 12 { 13 memData.BLogicID = i_BIndex; 14 i_BIndex++; 15 } 16 }
圖1中的索引是根據 memData.BLogicID生成的,我們再看看引文列表的索引是根據什么生成的?
1 if (Globals.BibTableAccessor._dictBibs.ContainsKey(Globals.MemoryDataKey)) 2 { 3 List<Bibliography> unquieBibliographies = this.GetUniqueBibliographies(Globals.BibTableAccessor._dictBibs[Globals.MemoryDataKey]); 4 this.CreateaReferencesList(cache, unquieBibliographies, journalStyle, wordStyle); 5 }
從上面的代碼可以看到 unquieBibliographies 這個來源正是內存中的題錄表,第4行代碼,正是實現引文列表的,它的內部實現是循環內存題錄表,然后根據循環的i變量來生成引文列表索引。
到這里,我就想,文中引文索引和引文列表的索引,都是和內存題錄表的存儲順序相關。那如果內存題錄表在第二次使用的時候,它的順序會不會變化?於是一個大膽的想法產生了:這個內存題錄表,在c#中是一個泛型List,那List的存儲在不排序的情況下到底會不會變呢?List是不是按我們Add的順序存儲,然后就不變呢?
為了揭開這些問題的答案,我偷偷地看了下List底層到底是怎么實現的?
看到構造函數里面,原來是構造了一個空的數組,默認容量是4。難怪以前比較厲害的同學,告誡我們給List適當地初始容量,這樣會提供List效率。當時,一臉懵逼,為什么呢?現在看了代碼才明白,
當我們Add一個元素的時候,判斷如果當前數組大小和元素的個數相等時,這時候要擴容,按照2倍的規則擴容的:
其實,我覺得執行這個擴容代碼倒不耗費什么性能。真正耗費性能的,應該是不斷地向內存申請存儲空間,我覺得這個事情應該耗費性能。按照我的想法,就算申請存儲空間也不耗費性能,那微軟會怎么做呢?是在原來數組的基礎上擴展容量,還是新實例化了一個數組,把原來的數組元素拷貝過去?
我們繼續研究代碼,此刻我是一邊寫,一邊研究,還沒有吃中午飯。
看到這里的代碼,我覺得一陣欣喜,微軟的做法,就是新構造了一個數組,把元素拷貝過去。那為什么不在原來的基礎上擴容呢?我想了想,所謂數組,就是一組連續的存儲空間,那微軟要在原來的基礎上擴展,何談容易呢?萬一這段空間周邊沒有空間呢?那就干脆把這樣的困難的事情交給操作系統完成好了。