亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

.Net泛型約束

2019-11-14 16:11:46
字體:
來源:轉載
供稿:網友

本文內容

  • 使用泛型約束的原因
  • 未綁定的類型參數
  • 作為約束的類型參數
  • 參考資料

當“設計模式”出現時,人們提“用接口編程”;后來,有了泛型,人們提“用泛型編程”。什么泛型?比如,單鏈表 LinkedList 場景,每個節點包含兩個字段:值和下一個節點的引用,其中,“值”既可以是 int,也可以是 string,甚至是對象,為每個數據類型都寫一個類,顯然太麻煩,此時就可以使用泛型 LinkedList <T>,T 表示 intstring 類型等等;再如,排序算法中很常見 Swap(ref int a, ref int b) 函數,可以交換兩個 int 類型,當然也可以是 string,用泛型也很合適。用 T 代表 intstring,甚至任何類型。

但問題是,實際項目中用 T 表示任何類型,顯然太粗放。比如,要是用表示動物和植物,動物和植物可能是接口或基類,顯然動物和植物不同,頂多都繼承生物基類或接口,我們倒是希望把 T 限定在動物或植物,這樣在定義相應的泛型類中就可以使用動物或植物的成員——這就是泛型約束。

這就完美了~

所以,實際項目中T 往往不是任何類型,而是代表某個類型、某個基類、某個接口,說是任何類型,只是泛型表達自己的理念而已。

下載 Demo

使用泛型約束的原因


如果把 T 限定在某個基類、某個接口上,那么泛型類中就可以使用那個基類或接口中的成員。

如果要檢查泛型列表中的某個項以確定它是否有效,或者將它與其他某個項進行比較,則編譯器必須在一定程度上保證它需要調用的運算符或方法將受到客戶端代碼可能指定的任何類型參數的支持。 這種保證是通過對泛型類定義應用一個或多個約束獲得的。

例如,基類約束告訴編譯器:僅此類型的對象或從此類型派生的對象才可用作類型參數。 一旦編譯器有了這個保證,它就能夠允許在泛型類中調用該類型的方法。約束是使用關鍵字 where 。

public class Employee
{
    PRivate string name;
    private int id;
 
    public Employee(string s, int i)
    {
        name = s;
        id = i;
    }
 
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
 
    public int ID
    {
        get { return id; }
        set { id = value; }
    }
}
/// <summary>
/// 員工單鏈表
/// </summary>
/// <typeparam name="T"></typeparam>
public class EmployeeList<T> where T : Employee
{
    /// <summary>
    /// Employee 節點 
    /// </summary>
    private class Node
    {
        private Node next;
        private T data;
 
        public Node(T t)
        {
            next = null;
            data = t;
        }
 
        public Node Next
        {
            get { return next; }
            set { next = value; }
        }
 
        public T Data
        {
            get { return data; }
            set { data = value; }
        }
    }
 
    private Node head;
 
    public EmployeeList()
    {
        head = null;
    }
 
    public void AddHead(T t)
    {
        Node n = new Node(t);
        n.Next = head;
        head = n;
    }
 
    public IEnumerator<T> GetEnumerator()
    {
        Node current = head;
 
        while (current != null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }
 
    public T FindFirstOccurrence(string s)
    {
        Node current = head;
        T t = null;
 
        while (current != null)
        {
            //The constraint enables access to the Name property.
            if (current.Data.Name == s)
            {
                t = current.Data;
                break;
            }
            else
            {
                current = current.Next;
            }
        }
        return t;
    }
}

where T : Employee”約束使泛型類可以使用 Employee.Name 屬性,即 current.Data.Name

類型為 T 的所有項,都保證是 Employee 對象或從 Employee 繼承的對象。

編譯器除了假設類型參數派生自 System.Object 以外,不會做其他任何假設。在希望強制兩個類型參數之間的繼承關系的情況下,可對泛型類使用參數類型約束。

在定義泛型類時,可以對客戶端代碼能夠在實例化類時用于類型參數的類型種類施加限制。 如果客戶端代碼嘗試使用某個約束所不允許的類型來實例化類,則會產生編譯時錯誤。 這些限制稱為約束。 約束是使用 where 關鍵字。下表列出了六種類型的約束:

約束

說明

T:結構

類型參數必須是值類型。

T:類

類型參數必須是引用類型;這一點也適用于任何類、接口、委托或數組類型。

T:new()

類型參數必須具有無參數的公共構造函數。 當與其他約束一起使用時,new() 約束必須最后指定。

T:<基類名>

類型參數必須是指定的基類或派生自指定的基類。

T:<接口名稱>

類型參數必須是指定的接口或實現指定的接口。 可以指定多個接口約束。 約束接口也可以是泛型的。

T:U

為 T 提供的類型參數必須是為 U 提供的參數或派生自為 U 提供的參數。

可以對同一類型參數應用多個約束,而且約束自身可以是泛型類型,如下所示:

class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
    // ...
}

這樣就可以增加約束類型及其繼承層次結構中的所有類型所支持的允許操作和方法。 因此,在設計泛型類或方法時,如果要對泛型成員執行除簡單賦值之外的任何操作或調用 System.Object 不支持的任何方法,您將需要對該類型參數應用約束。

在應用 where T : class 約束時,避免對類型參數使用 == 和 != 運算符,因為這些運算符僅測試引用是否相等,而不不是值是否相等。即使在用作參數的類型中重載這些運算符也是如此。下面代碼說明了這一點:即使 String 類重載 == 運算符,輸出也為 false。

public static void OpTest<T>(T s, T t) where T : class
{
    System.Console.WriteLine(s == t);
}
static void Main()
{
    string s1 = "target";
    System.Text.StringBuilder sb = new System.Text.StringBuilder("target");
    string s2 = sb.ToString();
    OpTest<string>(s1, s2);
}

因為編譯器在編譯時僅知道 T 是引用類型,因此必須使用對所有引用類型都有效的默認運算符。這就好像對 int 類型和 string 類型的比較,顯然不同。

如果必須測試值是否相等,那么可以使用 where T : IComparable<T> 約束,并在泛型類中實現該接口。

 

未綁定的類型參數


沒有約束的類型參數(如公共類 SampleClass<T>{} 中的 T)稱為未綁定的類型參數。 未綁定的類型參數具有以下規則:

  • 不能使用 != 和 == 運算符,因為無法保證具體類型參數能支持這些運算符。
  • 可以在它們與 System.Object 之間轉換,或將它們顯式轉換為任何接口類型。
  • 可以將它們與 null 進行比較。將未綁定的參數與 null 進行比較時,如果類型參數為值類型,則該比較將始終返回 false。

 

作為約束的類型參數


泛型類有泛型類型參數,泛型類的成員函數也有自己的泛型參數,但成員函數的泛型參數要約束在泛型類型參數上,此時就很用,如下示例所示:

class List<T>
{
    void Add<U>(List<U> items) where U : T {/*...*/}
}

上面示例中,泛型類型參數 T 在其成員函數 Add 方法中有一個類型約束 where U : T,其中,Add 方法中使用了泛型 U,而在 List 類中并沒有綁定的類型參數,沒有約束。

類型參數還可在泛型類定義中用作約束。注意,必須在尖括號中聲明此類型參數與任何其他類型的參數:

//Type parameter V is used as a type constraint.
public class SampleClass<T, U, V> where T : V { }

 

參考資料


  • 類型參數的約束

 

下載 Demo


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美另类极品videosbestfree| 欧美日韩国产精品| 日韩hd视频在线观看| 亚洲日本欧美日韩高观看| 国产日韩在线播放| 91在线高清视频| 丰满岳妇乱一区二区三区| 国产精品最新在线观看| 国产精品视频免费观看www| 欧美在线一级va免费观看| 青青草一区二区| 久久不射热爱视频精品| 国产精品久久久久久久一区探花| 久久男人的天堂| 国产精品成人av性教育| 亚洲香蕉在线观看| 中国人与牲禽动交精品| 亚洲国产精品久久91精品| 久久人人爽人人爽人人片av高请| 亚洲专区中文字幕| 亚洲国产成人av在线| 欧美一区二区三区……| 亚洲美女自拍视频| 色樱桃影院亚洲精品影院| www.亚洲成人| 久久亚洲影音av资源网| 亚洲午夜未删减在线观看| 亚洲男人天堂2024| 热99久久精品| 欧美理论电影网| 国产欧美精品久久久| 久久久国产精品免费| 国产精品亚洲视频在线观看| 欧美极品美女视频网站在线观看免费| 欧美黑人巨大精品一区二区| 欧美日韩一区二区在线播放| 欧美精品在线极品| 成人精品久久一区二区三区| 亚洲国产黄色片| 欧美精品第一页在线播放| 亚洲天堂免费在线| 2020久久国产精品| 精品久久中文字幕| 欧美大片欧美激情性色a∨久久| 中文字幕日韩欧美在线| 国产91露脸中文字幕在线| 国产成人a亚洲精品| 一区二区三区www| 91色视频在线观看| 国产日韩欧美成人| 精品国产成人在线| www欧美日韩| 国产精品无av码在线观看| 久久久久久久久国产| 国产精品精品一区二区三区午夜版| 中文字幕久热精品在线视频| 精品呦交小u女在线| 欧美极品少妇xxxxⅹ免费视频| 亚洲国产精品久久精品怡红院| 综合av色偷偷网| 国产xxx69麻豆国语对白| 91高清视频在线免费观看| 热99精品只有里视频精品| 成人写真视频福利网| 国产精品盗摄久久久| 欧美一区视频在线| 最近2019免费中文字幕视频三| 亚洲欧美另类在线观看| 欧美成人精品激情在线观看| 亚洲精品国精品久久99热| 欧美成人午夜激情| 欧美性极品少妇精品网站| 久久天天躁夜夜躁狠狠躁2022| 久久精品国产精品亚洲| 亚洲人成欧美中文字幕| 国产精品看片资源| 在线性视频日韩欧美| 韩国v欧美v日本v亚洲| 亚洲第一天堂av| 久久久久久久久久久亚洲| 久久天天躁狠狠躁夜夜av| 91在线视频导航| 久久久久久久久爱| 欧美日韩亚洲一区二| 欧美午夜视频在线观看| 欧美激情videos| 亚洲精品aⅴ中文字幕乱码| 欧美怡红院视频一区二区三区| 日韩精品免费综合视频在线播放| 色婷婷av一区二区三区在线观看| 亚洲一级片在线看| 91精品国产沙发| 色偷偷噜噜噜亚洲男人的天堂| 欧美一区二区色| 91亚洲国产成人精品性色| 97视频人免费观看| 国产精品一区二区女厕厕| 91精品国产综合久久香蕉的用户体验| 在线观看欧美日韩| 一区二区日韩精品| 亚洲一二在线观看| 欧美黄色免费网站| 国产精品久久久久一区二区| 91精品国产综合久久香蕉的用户体验| 日韩女优在线播放| 亚洲天堂2020| 欧美国产日韩xxxxx| 亚洲精品福利视频| 午夜精品久久久久久久男人的天堂| 欧洲成人午夜免费大片| 最近2019中文字幕在线高清| 91av在线播放视频| 成人网页在线免费观看| 久久躁日日躁aaaaxxxx| 日韩一区二区在线视频| 一夜七次郎国产精品亚洲| 精品亚洲精品福利线在观看| 欧美性猛交丰臀xxxxx网站| 久久这里有精品| 亚洲色图日韩av| 欧美在线观看视频| 日韩欧美国产黄色| 国产精品老女人视频| 日韩精品在线看| 国产一区欧美二区三区| 国产日韩在线精品av| 欧美极品xxxx| 8090成年在线看片午夜| 国产中文欧美精品| 日韩中文字幕欧美| 国产一区二区丝袜| 亚洲国产精品va在线观看黑人| 97精品国产aⅴ7777| 亚洲综合中文字幕在线| 国产精品美女999| 日韩在线视频国产| 热久久免费国产视频| 欧美性生活大片免费观看网址| 国产成人福利视频| 一本色道久久综合狠狠躁篇怎么玩| 国产日韩中文字幕| 中文日韩电影网站| 亚洲乱亚洲乱妇无码| 福利一区视频在线观看| 欧美性猛交99久久久久99按摩| 欧美精品亚州精品| 欧美老女人性视频| 成人免费观看49www在线观看| 欧美激情亚洲另类| 久久夜色精品亚洲噜噜国产mv| 亚洲国内精品视频| 久久人人看视频| 欧美成人久久久| 日韩欧美在线免费| 欧美在线一区二区三区四| 欧美最猛性xxxxx(亚洲精品)| 都市激情亚洲色图| 中文字幕亚洲自拍| 国产不卡在线观看| 亚洲人成人99网站| 国产色综合天天综合网| 亚洲精品黄网在线观看| 久久久久久中文字幕| 欧美日韩成人在线视频|