.NET(C#):使用KeyedCollection類型

來源:互聯網
上載者:User

目錄

  • 1. 基本使用
  • 2. 其他KeyedCollection變種
  • 3. 執行一個非抽象的KeyedCollection

 

 

返回目錄
1. 基本使用

這個類型貌似有些不起眼,在System.Collections.ObjectModel命名空間內,它在.NET 2.0時被加入,來看他的類型層次:

其實,他就是一個字典,只不過字典的鍵是從值中擷取的,看他的執行中發現內不是有一個Dictionary<TKey, TItem>欄位用來儲存資料,同時他也是支援比較子(IEqualityComparer<TKey>對象)的。但同時他的基類是Collection<TItem>類型,而Collection<TItem>執行了IList<T>, IList這些基本集合操作介面,所以KeyedCollection<TKey, TItem>在操作上會類似一個List<T>,T則代表KeyedCollection<TKey, TItem>中的TItem類型。這樣做的結果是你可以同時使用數組的索引值或者字典的鍵來訪問KeyedCollection的成員!

當然由於KeyedCollection<TKey, TItem>內部有一個Dictionary<TKey, TItem>,同時由於繼承自Collection<TItem>,所以內部也會有一個List<TItem>,所以相對Dictionary<TKey, TItem>類型他會佔用更多空間。

從ILSpy給出的繼承類上看,這個類在WCF中有過應用。

 

在使用上,比如,我們需要建立一個基於檔案對象(System.IO.FileInfo對象)的字典,字典的鍵就是檔案的路徑。此時就可以使用KeyedCollection類型。注意他是一個抽象類別,因為值怎樣包含鍵是無從得知的,所以需要執行這個抽象類別的GetKeyForItem方法。僅此而已,執行了這個方法後就可以使用KeyedCollection了。(注意本例中由於檔案路徑是不區分大小寫,所以需要在執行時設定IEqualityComparer<string>參數)

代碼:

//+ using System.Collections.ObjectModel

//+ using System.IO

class MyFileDictionary : KeyedCollection<string, FileInfo>

{

    //注意檔案路徑是不區分大小寫,所以需要設定IEqualityComparer<string>。

    public MyFileDictionary()

        : base(StringComparer.OrdinalIgnoreCase)

    { }

 

    //從FileInfo中返迴路徑作為Key。

    protected override string GetKeyForItem(FileInfo item)

    {

        return item.FullName;

    }

}

 

然後測試代碼:

//加入資料

var myFileDic = new MyFileDictionary();

foreach (var fileInfo in DriveInfo.GetDrives()[0].RootDirectory.GetFiles())

    myFileDic.Add(fileInfo);

 

//通過Index和Key擷取值,結果當然會輸出True,因為他們指向同一個對象。

Console.WriteLine(myFileDic[0] == myFileDic[myFileDic[0].FullName]);

 

 

返回目錄
2. 其他KeyedCollection變種

首先是安全執行緒的KeyedCollection執行。

注意:對於安全執行緒集合,強烈建議使用.NET 4.0中System.Collections.Concurrent命名空間內提供的高效能安全執行緒集合。讀者可參考MSDN。

事實上在.NET 3.0後,有一個安全執行緒的KeyedCollection執行,它包含在WCF程式集:System.ServiceModel.dll中。引用了這個程式集後,就可以使用System.Collections.Generic命名空間內的同步的KeyedCollection類型:SynchronizedKeyedCollection<K, T>類型了,注意他和KeyedCollection一樣,也是抽象類別。

 

其次中還有一個需要說的類型,他是KeyedByTypeCollection<TItem>類型,他直接繼承自KeyedCollection,從名字上就可以看出來,這種類型的KeyedCollection的鍵就是從值對象的類型中擷取的。

所以他只保留了TItem,從KeyedCollection<System.Type, TItem>類型中繼承。如:

 

注意:

在Silverlight 5中的System.ServiceModel.dll中(版本顯示是5.0.5.0):

 

SynchronizedCollection<T>類型為internal。且沒有SynchronizedKeyedCollection<K, T>類型。

 

 

 

返回目錄
3. 執行一個非抽象的KeyedCollection

由於KeyedCollection是抽象類別,所以每次需要具體的使用,你必須去定義一個繼承KeyedCollection的新類型。有些麻煩,當然,完全可以自己寫一個通用的非抽象KeyedCollection類型執行。使用一個負責轉換的委託欄位就可以。

如下代碼:

class MyKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>

{

    Func<TItem, TKey> _converter;

 

    public MyKeyedCollection(Func<TItem, TKey> converter, IEqualityComparer<TKey> comparer, int dictionaryCreationThreshold)

        : base(comparer, dictionaryCreationThreshold)

    {

        if (converter == null)

        {

            throw new ArgumentNullException("converter");

        }

        _converter = converter;

    }

 

    public MyKeyedCollection(Func<TItem, TKey> converter, IEqualityComparer<TKey> comparer)

        : this(converter, comparer, 0)

    { }

 

    public MyKeyedCollection(Func<TItem, TKey> converter)

        : this(converter, null, 0)

    { }

 

    protected override TKey GetKeyForItem(TItem item)

    {

        return _converter(item);

    }

}

 

那麼對於最上面那個儲存FileInfo的例子,我們就不需要專門定義新類型了,使用這個MyKeyedCollection類型就可以了,如下代碼:

var myFileDic = new MyKeyedCollection<string, FileInfo>(fileInfo => fileInfo.FullName, StringComparer.OrdinalIgnoreCase);

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.