程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則40:根據需求選擇集合(3)

Effective C#原則40:根據需求選擇集合(3)

編輯:關於C語言
齒數組裡的每一個新的維引用了另一個 foreach語句。然而,對於一個多維數組,每一個foreach語句都要產生代碼來檢 測數組每個維上的界線。foreach語句在每個維上生成特殊的代碼來迭代數組。 foreach循環生成的代碼與你這樣手寫是一樣的:

for ( int i = _theBoard.GetLowerBound( 0 );
 i <= _theBoard.GetUpperBound( 0 ); i++ )
 for( int j = _theBoard.GetLowerBound( 1 );
   j <= _theBoard.GetUpperBound( 1 ); j++ )
  _theBoard[ i, j ].PaintSquare( );

考慮在內層循環上所有對GetLowerBound 和 GetUpperBound 的調用,這看上去是認低效的,但這確實是很高效的結構。JIT 編譯器對數組類是很了解的,它們會緩存數組界線,而且可以識別內層的迭代界 線從而省略它們(參見原則11)。

數組類的兩個主要的不利因素可能會讓 你考慮使用.Net框架裡的其它集合類。第一個影響就是改變數組的大小:數組不 能動態的改變大小。如果你須要修改任意數組及任意維數的大小,你必須創建一 個新的數組,然後拷貝所有已經存在的元素到新的數組裡。改變大小要花時間: 因為新的數組要分配,而且所有的元素要拷貝到新的數組裡。盡管拷貝和移動在 托管堆上並不是像使用C和C++的年代那樣開銷昂貴,但還是很花時間。更重要的 是,它會讓數據使用陳舊。考慮下面的代碼:

private string [] _citIEs = new string[ 100 ];
public void SetDataSources( )
{
 myListBox.DataSource = _citIEs;
}
public void AddCity( string CityName )
{
 String[] tmp = new string[ _citIEs.Length + 1 ];
 _citIEs.CopyTo( tmp, 0 );
 tmp[ _citIEs.Length ] = CityName;
 _citIEs = tmp; // swap the storage.
}

即使在調用AddCity 之後,列表框的數據源還 是使用拷貝前的舊數據。你新添加的城市根本沒有在列表框中顯示。

ArrayList類是在數組上的一個高度抽象類。ArrayList集合混合了一維 數組和鏈表的語義。你可以在ArrayList使用迭代,而且你可以調整它的大小。 ArrayList基本上把所有責任都委托給了它所包含了數組上,這就是說ArrayList 類與數組類在性能上很接近。它的最大好處就是在你不清楚你的集合具體要多大 時,ArrayList類要比數組類好用得多。ArrayList可以隨時擴展和收縮。但你還 是要在移動和拷貝元素上有性能損失,但這些算法的代碼已經寫好了而且經過了 測試。因為內部存儲的數組已經封裝在ArrayList對象內,因此陳舊數據的情況 就不存在了:用戶的指針是指向ArrayList對象而不是內部的數組。.Net框架裡 的ArrayList集合有點類似C++中標准庫裡的向量類。

隊列和棧類在 System.Array類上提供了特殊的接口。這些特殊的接口是自定義的先進先出的隊 列接口和後進先出的棧接口。時刻記住,這些集合的內部存儲都是基於數組的。 在修改集合的大小時同樣會得到性能的損失。

(譯注:對於這樣的一些集 合,在初始化時都有一個大小的參數,應該盡可能的給定集合的容量大小,這裡 的大小並不是一次性申明和使用的,而是集合中的元素小於這個大小時,不會有 移動和拷貝元素的性能損失。因此合理的選擇這些集合的容量大小是很關鍵的。 隊列的默認大小是32,而棧的默認大小是10,ArrayList默認是0。而它們的構造 函數都有一個重載版本可以指定容量。)

.Net中的集合沒有包含鏈表 (linked list)結構。垃圾回收器的高效使得列表(list)結構在實際使用是占用 時間最小,因此也讓它成為了最佳選擇。如果你確實須要鏈表的行為,你有兩個 選擇。如果你因為希望經常添加和刪除裡面的元素而選擇了列表,那麼使用null 引用的字典類。簡單的存儲關鍵字,你就可以使用ListDictionary 類了,而且 它用鍵/值對應方式實現了單向鏈表。或者你可以選擇HybridDictionary類,這 是一個為小集合使用了ListDictionary的類,而且對於大集合會轉化到 HashTable上來。這些集合以及很多其它內容都在 System.Collections.Specialized 名字空間裡。然而,如果因為用戶想控制次 序而你想使用列表結構,你可以使用ArrayList 集合。ArrayList 可以在任何位 置上執行插入操作,即使它的內部是使用的數組存儲方式。

另外兩個類 支持基於字典的集合:SortedList 和Hashtable。它們都是包含鍵/值對應的。 SortedList以鍵進行排序,而Hashtable則沒有。Hashtable在給定的鍵上進行查 找時更快,但SortedList提供了基於鍵的有序迭代。Hashtable 通過鍵的散列值 進行查找。如果散列值是高效的,它的查找時間是一個常量,O(1)。有序列表是 使用的折半查找算法來查找關鍵值。這中一個對數的算法操作 :O(ln n)。

最後,就是BitArray類。正如它的名字所說的,它存儲位數值。 BitArray是以整數的數組來存儲數據的。每個整型存儲一個32位的二進制值。這 讓BitArray類是壓縮的,但它還是會降低性能。BitArray 上的每個get和set操 作要在存儲的整數上完成位操作,這要查找另外的31個位。BitArray 包含的一 些方法在很多值類型上實現了立即的Boolean操作:OR, XOR, AND, 和NOT。這些 方法用BitArray做為參數,而且BitArray可以用於快速的多位mask操作, BitArray 是一個為位操作進行優化了的容器;經常使用mask操作時,要存儲這 些位標記的數據時應該使用它。但不要用它灰替換一般用圖和Boolean值數組。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved