亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c#中協變與逆變的定義是什么

發布時間:2020-11-30 15:54:14 來源:億速云 閱讀:240 作者:Leah 欄目:開發技術

本篇文章給大家分享的是有關c#中協變與逆變的定義是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

基本概念

協變:能夠使用比原始指定的派生類型的派生程度更大(更具體)的類型。例如 IFoo<父類> = IFoo<子類>
逆變:能夠使用比原始指定的派生類型的派生程度更新(更抽象)的類型。例如 IBar<子類> = IBar<父類>

關鍵字out和in

協變和逆變在泛型參數中的表現方式,out關鍵字表示協變,in關鍵字表示逆變。二者只能在泛型接口或者委托中使用。

理解協變和逆變

看完上面的定義是不是一臉懵逼~~~。看不懂就對了,且定義語句的歧義性很大。讓我們大腦趕緊清空下!!首先記住一點明確的概念,類的多態展示一定是通過基類來表示,派生的具體類都是可轉化為基類,而不能走相反的流程。
下面我們用代碼直觀的表現下協變和逆變。

public class Animal
{
  public void Eat()
  { }
}

public class Dog : Animal
{
  public void Run()
  {
  }
}

這是一段很簡單的子類和父類的關系,我們進行一下簡單的轉化,應該很好理解,Dog子類可以用Animal父類展示,反過來則不可以,會編譯錯誤。

Dog dog = new Dog();
    Animal animal = dog;

    //error 編譯錯誤
    //Dog dog2 = animal;

那么我們做一點變化。

List<Dog> dogs = new List<Dog>();
    //error 編譯錯誤
    //List<Animal> animals_2 = dogs;

    IEnumerable<Dog> dogs_2 = dogs;
    IEnumerable<Animal> animals = dogs_2;

感覺到一點問題沒?Dog子類可以用Animal父類展示,使用List泛型就不可以了,但是IEnumerable泛型又可以。List<>和IEnumerable<>有什么不同?我們看下二者的定義即可發現端倪。

//IList定義
public interface IList<[NullableAttribute(2)] T> : ICollection<T>, IEnumerable<T>, IEnumerable
{}

//和IEnumerable定義
public interface IEnumerable<[NullableAttribute(2)] out T> : IEnumerable
{}

區別就在于 IEnumerable的泛型參數用了out協變標注,所以可以做正確的轉換。 這里也可以理解出什么時候需要使用in、out關鍵字:當你設計帶有泛型的基類且泛型類型可能存在擴展時,則需要考慮使用in或者out關鍵字修飾。
我們再看看官方的Action<>和Func<>類對協變和逆變的使用,先看定義:

public delegate void Action<[NullableAttribute(2)] in T>(T obj);

public delegate TResult Func<[NullableAttribute(2)] in T, [NullableAttribute(2)] out TResult>(T arg);

Action的泛型類型是入參,用in表示逆變,Func的第二個泛型類型TResult是出參,用out表示協變。
那么這樣看起來對in、out關鍵字的認識就很簡單明了了。看看轉換示例:

Action<Dog> action_dog = d => d.Run();
    Action<Animal> action_animal = a => a.Eat();

    //error 編譯錯誤。in
    //Action<Animal> action_animal_2 = action_dog;
		//Action泛型多態化
    Action<Dog> action_dog_2 = action_animal;

    Func<int, Dog> func_dog = a => { return new Dog(); };
    Func<int, Animal> func_animal = a => { return new Animal(); };

		//Func泛型多態化
    Func<int, Animal> func_animal_2 = func_dog;
    //error 編譯錯誤。out
    //Func<int, Dog> func_dog_2 = func_animal;

注意注釋編譯錯誤的語句,符合上面我們轉換的規則。對于入參,擴展類可以替代基類參數輸入,用in修飾;對于出參,擴展類可以替代基類返回輸出,用out修飾。相反則都不可以。

最后簡單總結下:

  • 什么是協變/逆變?不要去想官方定義!!!!只要記住out是協變,in是逆變即可。

  • 為什么需要使用協變-out、逆變-in。在泛型或委托中,如果不使用協變/逆變,那么泛型類型一個精確的、固定的某一類型。而使用協變/逆變的話,則泛型類型可以實現多態化。但必須區分入參使用in,出參使用out。

以上就是c#中協變與逆變的定義是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

洞口县| 文昌市| 周宁县| 台南县| 凤城市| 登封市| 封开县| 乌兰浩特市| 永城市| 三都| 喜德县| 博客| 保靖县| 平原县| 霍邱县| 留坝县| 河西区| 唐河县| 隆昌县| 棋牌| 舒城县| 平利县| 湘乡市| 景洪市| 合肥市| 利津县| 龙井市| 耒阳市| 深州市| 隆尧县| 新闻| 那曲县| 临朐县| 弋阳县| 锡林郭勒盟| 轮台县| 溆浦县| 屯留县| 迭部县| 灵石县| 玉林市|