程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 隱藏接口實現及ReadOnlyDictionary

隱藏接口實現及ReadOnlyDictionary

編輯:關於C#

接口代表著一種契約。但有的時候,接口所達成的契約並不適用於全部的場景,或者說,接口可能定 義得“太寬了”。這個時候,就有必要隱藏起某些接口成員。

然而,接口既然是一種“契約”,這就要求實現方必須為接口中的所有成員提供實現。所以,這裡說 到的“隱藏”,是指從對象的視角上隱藏。換言之,就是只有直接在對象上調用成員時,看不到某些接口 成員,但如果將對象強制轉換為接口類型,依然能看到所有的接口成員。

在C#中,接口的顯式實現可以幫助我們實現這一功能。下面的代碼可以幫助我們回憶一下接口的顯式 實現。

public interface IFoo
{
   void Foo();
}

public class Implement : IFoo
{
   // 顯式實現的接口成員:
   void IFoo.Foo() { /* 實現 */ }
}

public class Program
{
   static void Main()
   {
     Implement impl = new Implement();
     impl.Foo(); // 編譯錯誤。顯式實現的接口成員不能直接在對象上調用。

     IFoo foo = (IFoo)impl;
     foo.Foo(); // 編譯正確。
   }
}

下面舉個實際的例子。熟悉集合的朋友一定對ICollection<T>接口不陌生。該接口定義了集合 類型的一般成員,包括Add、Clear、Contains、CopyTo、GetEnumerator、Remove、Count等等。從集合的 角度來看,這些成員是很充分的。

但是,考慮這樣一個場景——希望實現一個只讀集合類,這個類不允許改變集合的內容。很明顯,只 讀集合也“是一個”集合,所以理應實現ICollection<T>接口。然而,接口中的Add、Clear和 Remove等方法無疑是破壞了集合的“只讀”特征。

因此,在實現只讀集合時,可以用這樣一種方式來實現只讀集合類——在類型中定義一個普通集合類 型的私有字段,也就是說,讓只讀集合“包裝”一個普通集合。這個只讀集合類依然實現 ICollection<T>接口,其中不會破壞“只讀”性質的成員,直接采用普通集合的實現;而對於會破 壞“只讀”性質的接口成員,則采用顯式接口實現的方式,從對象實例中隱藏掉該成員。

最後,為了防止用戶將對象強制轉換為接口類型,並試圖調用那些會破壞只讀性質的成員,需要在這 些成員的實現代碼中拋出異常(推薦使用NotSupportedException異常)。

例如,下面介紹一個ReadOnlyCollection類:

首先,令該類實現ICollection<T>接口,定義一個私有字段存放待包裝的普通集合,並在構造 器中為其賦值。

public class ReadOnlyCollection<T> : ICollection<T>
{
   private ICollection<T> _collection;

   public ReadOnlyCollection<ICollection<T> collection)
   {
     if(collection == null)
       throw new NotSupportedException();

     _collection = collection;
   }
}

對於那些不會破壞只讀性質的成員,直接利用普通集合的實現即可。這裡以Contains方法為例。

public bool Contains(T value)
{
   return _collection.Contains(value);
}

而對於那些會破壞只讀性質的成員,則采用接口成員的顯式實現,並在實現代碼中拋出異常。這裡以 Add方法為例。

void ICollection<T>.Add(T value)
{
   throw new NotSupportedException();
}

非常cool的是,.NET從2.0開始,已經為我們提供了這樣一個只讀集合,位於 System.Collections.ObjectModel命名空間中。

當然,這裡為了能夠簡單地說明問題,提供的代碼示例與.NET中的實現並不太一樣,有興趣的朋友可 以用.NET Reflector查看ReadOnlyCollection<T>類的源代碼。

遺憾的是,.NET只為我們提供了只讀集合,卻沒有提供只讀字典(或者是提供了,但我不知道)。所 以在這裡我仿照ReadOnlyCollection<T>類,編寫了一個ReadOnlyDictionary<TKey, TValue>類。

本文配套源碼

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