您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“C#泛型接口的協變和逆變怎么實現”,內容詳細,步驟清晰,細節處理妥當,希望這篇“C#泛型接口的協變和逆變怎么實現”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
假設:TSub是TParent的子類。
協變:如果一個泛型接口IFoo<T>,IFoo<TSub>可以轉換為IFoo<TParent>的話,我們稱這個過程為協變,IFoo支持對參數T的協變。
逆變:如果一個泛型接口IFoo<T>,IFoo<TParent>可以轉換為IFoo<TSub>的話,我們稱這個過程為逆變,IFoo支持對參數T的逆變。
通常只有具備繼承關系的對象才可以發生隱式類型轉換,如Base b=new sub()。
協變和逆變可以使得更多的類型之間能夠實現隱式類型轉換、類型安全性有了保障。
基于以上原因的同時、許多接口僅僅將類型參數用于參數或返回值。所以支持協變和逆變后泛型的使用上有了更大的靈活性
“TParent不能安全轉換成TSub”,是這兩個問題的共同原因。
我們定義一個接口IFoo。
interface IFoo<T> { void Method1(T param); T Method2(); }
我們看一下協變的過程:IFoo<TSub>轉換成IFoo<TParent>。
Method1:將TSub替換成TParent,Method1顯然存在 TParent到TSub的轉換。
Method2:返回值類型從TSub換成了TParent,是類型安全的。
所以支持協變的參數只能用在方法的返回值中。
再看一下逆變的過程:IFoo<TParent>轉換成IFoo<TSub>。
Method1:將TParent替換成TSub,Method1存在 TSub到TParent的轉換,是類型安全的。
Method2:返回值類型從TParent換成了TSub,是不安全的。
所以支持逆變的參數只能用在方法的參數中。
這其實是對3個問題的補充。
定義一個接口IFoo,既不支持協變,也不支持逆變。
interface IFoo<T> { void Method1(T param); T Method2(); }
實現接口IFoo
public class FooClass<T> : IFoo<T> { public void Method1(T param) { Console.WriteLine(default(T)); } public T Method2() { return default(T); } }
定義一個接口IBar支持對參數T的協變
interface IBar<out T> { T Method(); }
實現接口IBar
public class BarClass<T> : IBar<T> { public T Method() { return default(T); } }
定義一個接口IBaz支持對參數T的逆變
interface IBaz<in T> { void Method(T param); }
實現接口IBaz
public class BazClass<T> : IBaz<T> { public void Method(T param) { Console.WriteLine(param.ToString()); } }
定義兩個有繼承關系的類型,IParent和SubClass。
interface IParent { void DoSomething(); } public class SubClass : IParent { public void DoSomething() { Console.WriteLine("SubMethod"); } }
按照協變的邏輯,分別來使用IFoo和IBar。
//IFoo 不支持對參數T的協變 IFoo<SubClass> foo_sub = new FooClass<SubClass>(); IFoo<IParent> foo_parent = foo_sub;//編譯錯誤 //IBar 支持對參數T的協變 IBar<SubClass> bar_sub = new BarClass<SubClass>(); IBar<IParent> bar_parent = bar_sub;
foo_parent = foo_sub 會提示編譯時錯誤“無法將類型“IFoo<SubClass>”隱式轉換為“IFoo<IParent>”。存在一個顯式轉換(是否缺少強制轉換?)”
按照逆變的邏輯,分別來使用IFoo和IBaz。
//IFoo 對參數T逆變不相容 IFoo<IParent> foo_parent = null; IFoo<SubClass> foo_sub = foo_parent;//編譯錯誤 //IBaz 對參數T逆變相容 IBaz<IParent> baz_parent = null; IBaz<SubClass> baz_sub = baz_parent;
foo_sub = foo_parent 會提示編譯時錯誤“無法將類型“IFoo<IParent>”隱式轉換為“IFoo<ISub>”。存在一個顯式轉換(是否缺少強制轉換?)”
2.0中的定義:
public interface IEnumerable<T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
4.0中的定義:
public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
可以看到4.0中增加了對協變的支持。
可以在兩個版本試下, 下面的語句在2.0下會報錯。
List<SubClass> subarr = new List<SubClass>(); IEnumerable<IParent> parentarr = subarr;
讀到這里,這篇“C#泛型接口的協變和逆變怎么實現”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。