日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用泛型创建只读集合

發布時間:2025/1/21 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用泛型创建只读集合 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本系列文章翻譯O'Reilly 出版的《C# Cookbook》一書中的片段,僅供學習交流使用

?

4.9 使用泛型創建只讀集合

問題

您希望類中的一個集合里的信息可以被外界訪問,但不希望用戶改變這個集合。

解決方案

使用ReadOnlyCollection<T>包裝就很容易實現只讀的集合類。例子如,Lottery類包含了中獎號碼,它可以被訪問,但不允許被改變:

public?class?Lottery
????
{
????????
//?創建一個列表.
????????List<int>?_numbers?=?null;
????????
public?Lottery()
????????
{
????????????
//?初始化內部列表
????????????_numbers?=?new?List<int>(5);
????????????
//?添加值
????????????_numbers.Add(17);
????????????_numbers.Add(
21);
????????????_numbers.Add(
32);
????????????_numbers.Add(
44);
????????????_numbers.Add(
58);
????????}

????????
public?ReadOnlyCollection<int>?Results
????????
{
????????????
//?返回一份包裝后的結果
????????????get?{?return?new?ReadOnlyCollection<int>(_numbers);?}
????????}

}

?

Lottery有一個內部的List<int>,它包含了在構造方法中被填的中獎號碼。有趣的部分是它有一個公有屬性叫Results,通過返回的ReadOnlyCollection<int>類型可以看到其中的中獎號碼,從而使用戶通過返回的實例來使用它。

如果用戶試圖設置集合中的一個值,將引發一個編譯錯誤:

Lottery?tryYourLuck?=?new?Lottery();
????
//?打印結果.
????for?(int?i?=?0;?i?<?tryYourLuck.Results.Count;?i++)
????
{
????????Console.WriteLine(
"Lottery?Number?"?+?i?+?"?is?"?+?tryYourLuck.Results[i]);?
????}

????
//?改變中獎號碼!
????tryYourLuck.Results[0]=29;
????
//最后一行引發錯誤://?Error?26?//?Property?or?indexer
????
//?'System.Collections.ObjectModel.ReadOnlyCollection<int>.this[int]'
????
//?cannot?be?assigned?to?--?it?is?read?only
?

討論

ReadOnlyCollection的主要優勢是使用上的靈活性,可以在任何支持IListIList<T>的集合中把它做為接口使用。ReadOnlyCollection還可以象這樣包裝一般數組:

int?[]?items?=?new?int[3];
????items[
0]=0;
????items[
1]=1;
????items[
2]=2;
new?ReadOnlyCollection<int>(items);
?

這為類的只讀屬性的標準化提供了一種方法,并使得類庫使用人員習慣于這種簡單的只讀屬性返回類型。

閱讀參考

查看MSDN文檔中的“IList”和“Generic IList”主題。


4.10 使用相應的泛型版本替換Hashtable

問題

您希望通過使用相應的泛型版本替換所有Hashtable來增強應用程序性能并使得代碼更為易讀。當您發現這些數據結構中存放結構體和值類型會導致裝箱/拆箱操作,這就變得非常有必要了。

解決方案

替換所有已存在的System.Collections.Hashtable類為速度更快的System.Collections.Generic.Dictionary泛型類。

這有一個使用System.Collections.Hashtable對象的簡單例子:

public?static?void?UseNonGenericHashtable()
????
{
????????
//?創建并填充一個Hashtable.
????????Hashtable?numbers?=?new?Hashtable();
????????numbers.Add(
1,?"one");????//?鍵會導致裝箱操作
????????numbers.Add(2,?"two");????//?鍵會導致裝箱操作

????????
//?在Hashtable顯示所有的鍵/值對.
????????
//?在每次迭代中都會因為鍵導致一個拆箱操作
????????foreach?(DictionaryEntry?de?in?numbers)
????????
{
????????????Console.WriteLine(
"Key:?"?+?de.Key?+?"\tValue:?"?+?de.Value);
????????}

????????numbers.Clear();
}

?

下面是相同的代碼使用了System.Collections.Generic.Dictionary<T,U>對象:

public?static?void?UseGenericDictionary()
????
{
????????
//?創建并填充字典.
????????Dictionary<int,?string>?numbers?=?new?Dictionary<int,?string>();
????????numbers.Add(
1,?"one");
????????numbers.Add(
2,?"two");
????????
//?顯示字典中的所有鍵值對.
????????foreach?(KeyValuePair<int,?string>?kvp?in?numbers)
????????
{
????????????Console.WriteLine(
"Key:?"?+?kvp.Key?+?"\tValue:?"?+?kvp.Value);
????????}

????????numbers.Clear();
}

?

討論

對于應用程序中簡單的Hashtable實現,這種替換將十分容易。但有些地方需要注意,如泛型Dictionary類沒有實現ICloneable接口,而Hashtable類實現了。

4-2顯示了兩個類中的等價成員:

4-2 Hashtable和泛型Dictionary類的等價成員

Hashtable 類的成員

泛型 Dictionary 類的相應成員

N/A

Comparer 屬性

Count屬性

Count屬性

IsFixedSize屬性

((IDictionary)myDict).IsFixedSize

IsReadOnly屬性

((IDictionary)myDict).IsReadOnly

IsSynchronized屬性

((IDictionary)myDict).IsSynchronized

Item屬性

Item屬性

Keys屬性

Keys屬性

SyncRoot屬性

((IDictionary)myDict).SyncRoot

Values屬性

Values屬性

Add 方法

Add方法

Clear方法

Clear方法

Clone方法

在重載構造方法中接收一個 IDictionary<T,U> 類型

Contains方法

ContainsKey方法

ContainsKey方法

ContainsKey方法

ContainsValue方法

ContainsValue方法

CopyTo方法

((ICollection)myDict).CopyTo(arr,0)

Remove方法

Remove方法

Synchronized static方法

lock(myDictionary.SyncRoot) {…}

N/A

TRyGetValue方法

?

4-2中,并非所有的HashtableDictionary的成員都一一對應。我們從屬性開始,注意,只有CountKeysValuesItem屬性在兩個類中都存在。為了彌補Dictionary中缺少的屬性,需要把它轉化為IDictionary類型。下面的代碼演示了如果進行這些轉換以獲得缺少的屬性:

Dictionary<int,?string>?numbers?=?new?Dictionary<int,?string>();
????Console.WriteLine(((IDictionary)numbers).IsReadOnly);
????Console.WriteLine(((IDictionary)numbers).IsFixedSize);
????Console.WriteLine(((IDictionary)numbers).IsSynchronized);
Console.WriteLine(((IDictionary)numbers).SyncRoot);
?

注意,由于缺少返回一個泛型字典同步版本的代碼,IsSynchronized屬性將總是返回falseSyncRoot屬性在被調用時總是返回相同的對象。實際上這個屬性返回的是this指針。微軟已經決定移除泛型集合類的創建同步包裝的功能。

做為替代,他們推薦使用lock關鍵字鎖住整個集合或其他同步對象類型以滿足您的需求。

因為在泛型字典類中也缺少了克隆方法(實際是是因為這個類沒有實現ICloneable接口),您可以轉而使用重載的構造方法來接收一個IDictionary<T,U>類型:

?//?創建并填充字典.
????Dictionary<int,?string>?numbers?=?new?Dictionary<int,?string>();
????numbers.Add(
1,?"one");
????numbers.Add(
2,?"two");
????
//?顯示原字典的鍵/值對.
????foreach?(KeyValuePair<int,?string>?kvp?in?numbers)
????
{
????????Console.WriteLine(
"Original?Key:?"?+?kvp.Key?+?"\tValue:?"?+?kvp.Value);
????}

????
//?克隆字典對象.
????Dictionary<int,?string>?clonedNumbers?=?new?Dictionary<int,?string>(numbers);
????
//?顯示克隆字典中的鍵/值對.
????foreach?(KeyValuePair<int,?string>?kvp?in?numbers)
????
{
????????Console.WriteLine(
"Cloned?Key:?"?+?kvp.Key?+?"\tValue:?"?+?kvp.Value);
}

?

還有兩個Dictionary類中缺少的方法:ContainsCopyTo方法。Contains方法的功能在Dictionary類中很容易被實現。在Hashtable類中,Cintains方法和ContainsKey方法有相同的行為,因此您可以在Dictionary類中簡單地使用ContainsKey方法來模擬Hashtable類中的Contains方法:

?//?創建和填充字典.
????Dictionary<int,?string>?numbers?=?new?Dictionary<int,?string>();
????numbers.Add(
1,?"one");
????numbers.Add(
2,?"two");
????Console.WriteLine(
"numbers.ContainsKey(1)?==?"?+?numbers.ContainsKey(1));?
Console.WriteLine(
"numbers.ContainsKey(3)?==?"?+?numbers.ContainsKey(3));
CopyTo方法也很容易在Dictionary類中被模擬,但需要做一些額外的工作:
????
//?創建和填充字典.
????Dictionary<int,?string>?numbers?=?new?Dictionary<int,?string>();
????numbers.Add(
1,?"one");
????numbers.Add(
2,?"two");
????
//?顯示字典中的所有鍵/值對.
????foreach?(KeyValuePair<int,?string>?kvp?in?numbers)
????
{
????????Console.WriteLine(
"Key:?"?+?kvp.Key?+?"\tValue:?"?+?kvp.Value);
????}

????
//?創建對象數組來拷貝字典對象中的信息.?
????KeyValuePair<int,?string>[]?objs?=?new?KeyValuePair<int,?
string>[numbers.Count];
????
//?調用字典中的CopyTo方法
????
//?把字典中的所有鍵/值對對象拷貝到objs中
????((IDictionary)numbers).CopyTo(objs,?0);
????
//?顯示objs[]中的所有鍵/值對.
????foreach?(KeyValuePair<int,?string>?kvp?in?objs)
????
{
????????Console.WriteLine(
"Key:?"?+?kvp.Key?+?"\tValue:?"?+?kvp.Value);
}

?

調用Dictionary對象中的CopyTo方法需要創建一個KeyValuePair<T,U>對象數組,它用于在CopyTo方法被調用之后,控制字典對象中的所有KeyValuePair<T,U>對象。接下來numbers字典對象被轉換為IDictionary類型以調用CopyTo方法。一旦CopyTo方法被調用,objs數組將包含原numbers對象中的所有KeyValuePair<T,U>對象。注意objs數組迭代時使用了foreach循環,這點和numbers對象是相同的。

閱讀參考

查看MSDN文檔中的“System.Collections.Hashtable Class”和“System.Collections.Generic.Dictionary Class"主題。


與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的使用泛型创建只读集合的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。