今天回憶了之前看的《深入理解C#》這本書中的泛型章節,其中對泛型的可變性的理解。泛型可變性分兩種:協變和逆變。逆變也又稱為抗變。 怎麼理解這兩個名詞的意思: ①:協變即為在泛型介面類型中使用out標識的類型參數。協變的字面意思是“與變化的方向相同”②逆變那就是用in來標識的泛型介面類型的類型參數。逆 ...
今天回憶了之前看的《深入理解C#》這本書中的泛型章節,其中對泛型的可變性的理解。泛型可變性分兩種:協變和逆變。逆變也又稱為抗變。
怎麼理解這兩個名詞的意思:
①:協變即為在泛型介面類型中使用out標識的類型參數。協變的字面意思是“與變化的方向相同”②逆變那就是用in來標識的泛型介面類型的類型參數。逆變的字面意思是“與變化的方向相反”
需要註意的是無論是協變還是逆變也只能在泛型介面中來使用。
先來舉個基本的例子,來加強你對可變性的理解。在C#中有隱式類型轉換,比如:
string str = "nibian"; object str1 = str; Console.WriteLine(str1);
大家都知道string類型是object類型的子類型,即string->object為子->父;從子類型到父類型的轉換是隱式類型轉換。
舉個例子:
interface IDemo<out T> { T Method(string str); } class One : IDemo<string> { public string Method(string str) { return str; } } class Two : IDemo<object> { public object Method(string str) { return str; } } class Program { static void Main(string[] args) { IDemo<string> one = new One(); IDemo<object> two; two = one; Console.WriteLine(two.Method("2222")); } }
因為string是object類型的子類,在這裡IDemo<string>和IDemo<object>類型之間也存在著類型轉換的,從IDemo<string>向IDemo<object>進行的轉換可以看成是子類型向父類型的隱式轉換,它的這個用法就是協變。(這裡必須要用out)
相反的我們在來看一下有關逆變的代碼:
interface IDemo<in T> { string Method(T str); } class One : IDemo<string> { public string Method(string str) { return str; } } class Two : IDemo<object> { public string Method(object str) { return str.ToString(); } } class Program { static void Main(string[] args) { IDemo<object> two = new Two(); IDemo<string> one; one = two; Console.WriteLine(one.Method("2222")); } }
同樣的從IDemo<object>類型向IDemo<string>類型的轉換,但是在這裡我們卻將父類型隱式轉換為子類型的用法叫逆變。(這裡必須要用in)
總結:協變和逆變就是在泛型介面類型將類型參數作為輸入和輸出的情況下,對類型間進行隱式轉換的規律。