中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

C#高級靜態語言效率利器之泛型怎么引用

發布時間:2023-02-27 14:12:32 來源:億速云 閱讀:112 作者:iii 欄目:開發技術

這篇文章主要介紹“C#高級靜態語言效率利器之泛型怎么引用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“C#高級靜態語言效率利器之泛型怎么引用”文章能幫助大家解決問題。

引入

所謂泛型,就是創建一個函數,對所有數據類型都生效。最常見的例子就是運算符,畢竟1+1=2,1.0+1.0=2.0,足以看出+是對多種數據類型起作用的。

但是,如想創建一個函數add(int a, int b),那么輸入add(1.0, 1.0)是肯定要報錯的,VS直接就給標紅了。

泛型的出現,就很好地解決了這個尷尬的問題

T add<T>(T a, T b) 
{
    dynamic d1 = a;
    dynamic d2 = b;
    return (T)(d1 + d2);
}

Console.WriteLine(add<int>(1, 1));
Console.WriteLine(add<double>(1.0, 1.0));

上面代碼中,T表示某種數據類型,在調用函數add時,根據add后面的<>加以聲明。

但如果就此就寫return a+b顯然也是不行的,因為+這種運算符并沒有對T進行重載,編輯器并不會允許兩種未知的類型相加。

這個時候就需要用到dynamic,用來讓編輯器放棄類型檢查,將任何可能發生的錯誤都留給運行階段。

最后,運行結果為

2
2

類型約束

dynamic用著確實爽,但后果就是責任自負,這玩意要是用在團隊協作的場合,簡直就是災難,畢竟并非所有對象都可以駕馭加法。

所以,C#的泛型,是可以被約束的泛型,關鍵就是where,將上述代碼寫為

T add<T>(T a, T b) where T : struct{
    dynamic d1 = a;
    dynamic d2 = b;
    return (T)(d1 + d2);
}

where T : struct表示T必須是數值類型的一種,所以編譯器的類型檢查仍會發揮作用,在調用add時,如果T不是數值類型,就會報錯。

C#一共有5種約束方案,列表如下

類別條件
structT必須是值類型
classT必須是引用類型
new()T必須有無參數的構造函數
基類名T必須是基類或派生自基類
接口名T必須是指定接口
裸類型

 不同類型的約束,或相同類型不同種類的約束,一般是可以混用的,如果不能混用,編譯器會提醒。比如struct幾乎不能和其他類型混用。如果new()參與了約束,則放在最后。

子類泛型

除了函數可以采用泛型,類當然也可以,不僅可以,而且還能繼承。

class MyList<T>
{
    public T[] a;
    public MyList(){}       //無參數的構造函數,用于繼承
    public MyList(int n){
        a = new T[n];
    }
    public T this[int index]{
        get => a[index];
        set => a[index] = value;
    }

}

MyList相當于是給數組套了一層殼,其構造函數并不存在什么難以理解的地方,唯一有些問題的可能是下面的索引器public T this[int index],這種寫法可以實現方括號形式的索引。

可以測試一下

var a = new MyList<int>(5);
for (int i = 0; i < 5; i++)
{
    a[i] = i;
    Console.WriteLine(a[i]);
}

結果就不粘貼了,接下來新建一個子類

class MyStack<T> : MyList<T>
{
    public MyStack(int n)
    {
        a = new T[n];
    }
    public T Pop()
    {
        T p = a[a.Length- 1];
        a = a[0..(a.Length-1)];
        return p;
    }
}

然后測試一下

var a = new MyStack<int>(3);
for (int i = 0; i < 3; i++)
{
    a[i] = i;
}

for (int i = 0; i < 3; i++)
{
    Console.WriteLine(a.Pop());
}

結果為

2
1
0

常用的泛型數據結構

C#通過泛型定義了很多數據結構,例如在講解switch...case時提到的字典

Dictionary<int, string> card = new Dictionary<int, string>
{
    {1,"A" },
    {11, "J" },
    {12, "Q" },
    {13, "K" }
};

這種<U, V>的寫法,正是泛型的特點,其中U, V就是可以隨意聲明的變量。如果查看字典的類型參數,可以發現其定義方法是這樣的

public class Dictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, ... where TKey : notnull

考慮到本節并不是為了將面向對象,所以字典繼承的那一大坨類就省略了,關鍵是where Tkey:notnull,也就是說,字典對鍵值對的要求只有一個,就是鍵不得為null。

除了字典之外,還有一些常見的數據結構采用了泛型,列表如下,沒事兒可以練習練習。

數據結構說明常用方法
List<T>泛型列表Add, Remove, RemoveAt
LinkedList<T>雙端鏈表AddFirst, AddLast, RemoveFirst, RemoveLast
Queue<T>先進先出列表Enqueue, Dequeue
Stack<T>棧,先進后出Push, Pop

泛型委托

委托,是函數的函數;泛型,可以讓函數的參數類型更加靈活,二者結合在一起,就是更加靈活的函數的函數,即泛型委托。

只要學過了泛型和委托,那么對泛型委托將毫無理解上的難度,回想前面定義的運算符委托

delegate int Op(int a, int b);

再回想定義泛型時的<T>,那么泛型委托可以非常簡單地定義出來

delegate T Op<T>(T a, T b);

然后就可以根據委托,建立一個泛型函數

T add<T>(T a, T b)
{
    dynamic d1 = a;
    dynamic d2 = b;
    return (T)(d1 + d2);
}
var addTest = new Op<int>(add<int>);
//也可以省略add后的<int>,寫成下面的形式
//var addTest = new Op<int>(add);
Console.WriteLine(addTest(3, 5));

運行之后控制臺出現了8,就是這么簡單。

關于“C#高級靜態語言效率利器之泛型怎么引用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

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

AI

航空| 巴青县| 瑞金市| 揭西县| 惠安县| 称多县| 西华县| 甘德县| 平遥县| 来宾市| 大理市| 芮城县| 马尔康县| 科技| 阿荣旗| 花垣县| 澄迈县| 棋牌| 靖安县| 元谋县| 武功县| 绥滨县| 德惠市| 叙永县| 拉萨市| 城固县| 定南县| 西乌珠穆沁旗| 平遥县| 康定县| 蓝山县| 辽源市| 桂林市| 南陵县| 三穗县| 合肥市| 格尔木市| 通山县| 玉门市| 莱西市| 甘孜|