1. 程式人生 > 實用技巧 >C# 協變 逆變

C# 協變 逆變

逆變,協變

定義:

逆變 :指能夠使用比原始指定的派生型別的 派生程度更小(不太具體的)的型別。

協變 :能夠使用比原始指定的派生型別的 派生程度更大(更具體的)的型別。

看了上面一臉懵逼,下面會解釋

示例

這是用來講解例子的兩個類

public class Father
{
    public string Name { get; set; }
}

public class Son : Father
{
    public int Age { get; set; }
}

協變 out

Father f = new Son();

先來看這一句 這是我們熟悉的, 因為Son繼承自Father, 所以編譯可以通過。

我們可以認為:

Father(基類) 相對於 Son(子類) 是派生程度更大(更具體的)的型別。

Son(子類) 相對於 Father(基類) 派生程度更小(不太具體的)的型別

再來看這一句

List<Son> sons = new List<Son>();
List<Father> fathers = sons; // error

為什麼為編譯失敗呢,因為編譯器知道 Father 和 Son 是繼承關係,但是不知道List< Father > 和 List< Son > 是什麼關係。

List<Son> sons = new List<Son>();
IEnumerable<Father> fathers = sons; // success

這是協變,可以允許使用比原指定型別派生程度更大(更具體的)的型別。

逆變 in
逆變也稱為不正常的變化
比如Father轉為Son,這肯定不行。

Action <Father> func1 = new Action<Father>(a => { Console.WriteLine($"{a.Name}"); });

func1是輸出Father的Name,那既然Father能輸出Name為什麼Son不能輸出Name呢? 如下就可以,因為Action 是逆變

Action <Father> func1 = new Action<Father>(a => { Console.WriteLine($"{a.Name}"); });
Action <Son> func2 = func1;

這是逆變 可以使用比原指定型別派生程度更小(不太具體的)的型別。