泛型(Generic)


一、泛型的引入

  1. 泛型---泛:寬泛的---不確定的; 型:類型---不確定的類型

  2. 無處不在

  3. 調用普通方法的時候,參數類型在聲明的時候就確定了,調用時按照類型傳遞參數即可;

  4. Object類型作為參數,可以傳遞不同的類型進去。

  5. 泛型方法---做到了性能高---可以一個方法滿足不同類型的需求

二、泛型的聲明設計思想

  1. 泛型方法:在方法名稱后面多一個尖括號new class Base() { },尖括號中有占位符
  2. 延遲聲明:在執行調用時聲明
  3. 占位符:T 類型參數——類型變量
  4. 類型參數當做方法的參數的時候,明確參數類型

三、泛型的原理

1.在高級語言中,定義的泛型T,在計算機執行的執行的時候,必須是一個具體的類型;

在這里插入圖片描述

2.在底層看到,生成的結果是:List `[T] Dictionary 2 [TKey,TValue]

3.編譯器必須能夠支持泛型

4.CLR運行時環境也必須要支持泛型

5.泛型是框架升級支持的——泛型並非是語法糖

四、泛型的使用

  1. 泛型方法----可以一個方法滿足不同類型的需求
  2. 泛型接口----可以一個接口滿足不同類型的需求---尖括號+占位符
  3. 泛型類------可以一個類型滿足不同類型的需求---尖括號+占位符
  4. 泛型委托----可以一個委托滿足不同類型的需求

實例代碼

 { 
                       //泛型方法                    
                    {
                        GenericInterfac<string> sgenericInterfac = null;
                       GenericInterfac<DateTime> dtgenericInterfac = null;
                    } 
                    {
                        GenericAbstractClass<string> sGenericClass = null;
                        GenericAbstractClass<DateTime> dtGenericClass = null;
                        GenericAbstractClass<int> iGenericClass = null;
                        //sGenericClass  dtGenericClass  iGenericClass 三者是什么關系?--一沒有關系都沒有
                    }
                    {
                       Genericdelegate<string> sGenericdelegate = null;
                       Genericdelegate<DateTime> dtGenericdelegate = null;
                    }  
 }

五、泛型的約束

為什要有泛型約束?

  • Object類型有安全問題,代碼可能會存在隱患,但是編譯器監測不到原因
  • 如何避免類型安全問題--泛型--不存在類型安全問題
    在這里插入圖片描述

1.基類約束

  • 就是把類型參數當做Cart
  • 調用---就可以傳遞Cart或者Cart的子類型
  • 泛型約束:要么不讓你進來,如果讓你進來,就一定是沒有問題
  • 直接new T()會報錯,可能沒有無參數構造構造函數

示列:

class MyGenericClass<T>
where T : Cart
{
}

2.接口約束

  • 把這個T 當做ICart
  • 就只能傳遞ICart 這個接口或者是實現過這個接口的類
  • 就可以增加功能,可以獲取新的功能

示列:

public class MyGenericClass<T> where T:ICart { }

3.引用類型約束

  • 就只能傳遞類型進來
  • 直接new T()會報錯,可能沒有無參數構造構造函數

示列:

public class MyGenericClass<T> where T:class

4.值類型約束

  • 就只能傳遞值類型進來

示列:

public static void ShowStruct<T>(T t) where T : struct
        {
            
        }

5.無參構造函數約束

  • 必須有一個無參數構造函數才能當做參數傳入

示列:

public static void ShowNew<T>(T t) where T : new()
        {
            T model = new T();
        }

6.枚舉約束

  • 必須是一個枚舉類型才能傳入

示列:

public static void ShowEnum<T>(T t) where T : Enum
        {
             
        }

六、協變與逆變

1.泛型的協變/逆變

協變/逆變是一種高級約束,是為了規避:

  • 把子類做參數,卻把父類當參數傳入
  • 把子類做返回值,卻返回的時候,返回了一個父類

2.協變逆變

  • 只針對於泛型接口和泛型委托的

3.協變

  • 協變: 就可以讓右邊用子類,能讓左邊用父類

  • 協變:Out 類型參數只能做返回值 ,不能做參數

4.逆變

  • 逆變:就可以讓右邊用父類;左邊用子類
  • 逆變 In : 只能做參數 ,不能做返回值

5.協變逆變的存在

  • 就是為了滿足常規場景添加一個避開風險的約束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM