程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# Keywords Series 6 in(Generic Modifier)&out(Generi

C# Keywords Series 6 in(Generic Modifier)&out(Generi

編輯:C#入門知識

 本篇文章主要講述 in 和 out 兩個泛型參數修飾符。對於這兩個關鍵字,樓主也是各種不懂,要學會使用這兩個關鍵字,必須先理解協變和逆變的概念。     協變和逆變     簡單定義就是:協變就是泛型接口從子類向父類轉化,逆變就是父類向子類轉換。下面兩種轉換就是協變和逆變:   [csharp]   IEnumerable<string> strs = null;   IEnumerable<object> objs = null;   objs = strs;    // “子類”向“父類”轉換,即泛型接口的協變   strs = objs;    // “父類”向“子類”轉換,即泛型接口的逆變,這個會報錯,IEnumerable 接口用 out 修飾泛型參數,限定了只能協變,這裡只是為了說明兩個轉換的區別       上面的代碼,IEnumerable<string> 和 IEnumerable<object> 表面上看有點類似父類和子類的關系,實際上他們根本沒有任何繼承關系,可以認為是兩個獨立的類。而 .NET 4.0開始,有條件的允許上面協變和逆變的轉換,這裡就用到 in 或 out 關鍵字修飾泛型參數 T 的使用范圍。     可以看下 IEnumerable 的聲明       [csharp]   [TypeDependency("System.SZArrayHelper")]      public interface IEnumerable<out T> : IEnumerable      {             IEnumerator<T> GetEnumerator();      }           如果 IEnumerable 接口用 in 修飾泛型參數的話,那麼逆變(即 strs = objs;) 是可以通過編譯的。所以我們總結起來就是: 用 out 來修飾泛型參數時允許協變,用 in來修飾泛型參數允許逆變。     說到這裡,這兩個關鍵字倒沒什麼講的,那為什麼.NET 4.0開始引入協變逆變。   [csharp]   List<object> list = new List<object>();   list.AddRange(strs); // 如果沒有協變(子類對於父類的隱式轉換),這行代碼會報錯   list.AddRange(objs);        上面代碼,如果IEnumerable 接口沒有用 out 修飾泛型參數,那就會編譯報錯。而且你得寫個循環,將 strs 一個個轉換為 IEnumerable<object>,為了避免這樣的麻煩,支持協變的話,就可以直接轉換,不會編譯報錯。所有協變逆變的問題實際上都源於一個根本的原則: 子類可以向父類隱式轉換,父類不能向子類隱式轉換。     最後再看一個完整的例子,來看看 in 和 out 的使用方法:   [csharp]   class Program   {       static void Main(string[] args)       {           IContravariant<Object> iobj1 = new Sample<Object>();           IContravariant<String> istr1 = new Sample<String>();           ICovariant<Object> iobj2 = new Sample<Object>();           ICovariant<String> istr2 = new Sample<String>();           istr1 = iobj1;  // in 修飾符實現協變(子類對於父類的隱式轉換)           iobj2 = istr2;  // out 修飾符實現逆變(父類對於子類的隱式轉換)        }   }      // 逆變接口.   interface IContravariant<in A> { }      // 協變接口.   interface ICovariant<out R> { }      // 實現協變逆變接口的類.   class Sample<A> : IContravariant<A> ,ICovariant<A>   { }           

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