您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了C#的協變和逆變是什么,內容簡而易懂,希望大家可以學習一下,學習完之后肯定會有收獲的,下面讓小編帶大家一起來看看吧。
從C# 4.0開始,泛型接口和泛型委托都支持協變和逆變,由于歷史原因,數組也支持協變。
里氏替換原則:任何基類可以出現的地方,子類一定可以出現。
協變(out)
abstract class Animal {} class Dog : Animal {} class Cat : Animal {} interface IPoppable<T> { T Pop(); } class MyStack<T> : IPoppable<T> { private int _pos; private readonly T[] _data = new T[100]; public void Push(T obj) => _data[_pos++] = obj; public T Pop() => _data[--_pos]; }
以下代碼是無法通過編譯的
var dogs = new MyStack<Dog>(); IPoppable<Animal> animals1 = dogs; // 此處會發生編譯錯誤 Stack<Animal> animals2 = dogs; // 此處會發生編譯錯誤
此時,我們如果需要為動物園飼養員新增一個輸入參數為Stack<Animal>飼喂的方法,一個比較好的方法是新增一個約束泛型方法:
class Zookeeper { public static void Feed<T>(IPoppable<T> animals) where T : Animal {} } // 或者 class Zookeeper { public static void Feed<T>(Stack<T> animals) where T : Animal {} } // Main Zookeeper.Feed(dogs);
現在,C#增加了協變
使IPoppable<T>接口支持協變
// 僅僅增加了一個 out 聲明 interface IPoppable<out T> { T Pop(); }
簡化Feed方法
class Zookeeper { public static void Feed(IPoppable<Animal> animals) {} } // Main Zookeeper.Feed(dogs);
協變的天然特性——僅可作為方法返回值,接口(或委托)外部無法進行元素添加,確保了泛型類型安全性,所以不用擔心Dog的集合中出現Cat
常用的支持協變的接口和委托有:
IEnumerable<Dog> dogs = Enumerable.Empty<Dog>(); IEnumerable<Animal> animals = dogs; var dogList = new List<Dog>(); IEnumerable<Animal> animals = dogList;
另外,由于歷史原因,數組也支持協變,例如
var dogs = new Dog[10]; Animal[] animals = dogs;
但是無法保證類型安全性,以下代碼可正常進行編譯,但是運行時會報錯
animals[0] = new Cat(); // 運行時會報錯
逆變(in)
abstract class Animal {} class Dog : Animal {} class Cat : Animal {} interface IPushable<in T> { void Push(T obj); } class MyStack<T> : IPushable<T> { private int _pos; private readonly T[] _data = new T[100]; public void Push(T obj) => _data[_pos++] = obj; public T Pop() => _data[--_pos]; } // Main var animals = new MyStack<Animal>(); animals.Push(new Cat()); IPushable<Dog> dogs = animals; dogs.Push(new Dog());
逆變的天然特性——僅可作為方法輸入參數,接口(或委托)無法進行元素獲取,即只能將子類賦值到父類上,進而保證了類型安全性。
另外,常用支持逆變的接口和委托有:
Action<Animal> animalAction = new Action<Animal>(a => { }); Action<Dog> DogAction = animalAction;
以上就是關于C#的協變和逆變是什么的內容,如果你們有學習到知識或者技能,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。