<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      泛型的學習

      泛型的學習

      一、泛型的引入

      1. 泛型---泛:寬泛的--不確定的; 型:類型---不確定的類型
      2. 無處不在的
      3. 調用普通方法的時候,參數類型在聲明的時候就確定了,調用按照類型傳遞參數即可
        a. 如果有100個類型---100個方法?--很累
        b. 有沒有能夠做一個方法可以能夠滿足不同類型的需求呢?

      傳統方法

         public static   class CommonMethod
          {
              public static void ShowInt(int Parameter)
              {
                  Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
              }
      
              public static void ShowString(string Parameter)
              {
                  Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
              }
      
              public static void ShowDateTime(DateTime Parameter)
              {
                  Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
              }     
          }
      
      1. Object類型作為參數 ----可以傳遞不同的參數
        a. 任何子類出現的地址都可以讓父類來代替
        b. 萬物皆對象---任何一個類型都是繼承自Object

      使用Object類型

         public static   class CommonMethod
          {
              public static void ShowObject(object Parameter)
              {
                  Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
              }
          }
      
      1. 問題
        a. 性能問題 ---裝箱拆箱---在c#語法中,按照聲明時決定類型的(棧、托管堆)
        b. 類型安全問題

      我們通過一個例子來體現性能的問題

      public  class PerformanceTest
          {
              public static void Show()
              {
                  int ivalue = 1234;
                  //消耗的時間
                  long commonSecond = 0;
                  long objectSecond = 0;
                  long genericSecond = 0;
      
                  {
                      Stopwatch sw = new Stopwatch(); 
                      sw.Start();
                      for (int i = 0; i < 1000_000_000; i++) {
                          ShowInt(ivalue);
                      }
                     sw.Stop();
                      commonSecond = sw.ElapsedMilliseconds;
                  }
      
                  {
                      Stopwatch sw = new Stopwatch();
                      sw.Start();
                      for (int i = 0; i < 1000_000_000; i++)
                      {
                          ShowObject(ivalue);
                      }
                      sw.Stop();
                      objectSecond = sw.ElapsedMilliseconds;
                  }
      
                  {
                      Stopwatch sw = new Stopwatch();
                      sw.Start();
                      for (int i = 0; i < 1000_000_000; i++)
                      {
                          Show(ivalue);
                      }
                      sw.Stop();
                      genericSecond = sw.ElapsedMilliseconds;
                  }
                  Console.WriteLine($"commonSecond: {commonSecond} objectSecond: {objectSecond} genericSecond :{genericSecond} ");
              }
      
      
              
      
      
              private static void ShowInt(int r)
              {
      
              }
      
              private static void ShowObject(object o)
              {
      
              }
      
      
               private static void Show<T>(T parameter)
              {
      
              }
      
          }
      

      結果為:

      1. 有沒有既性能好,也能夠支持多種類型的方法呢?---泛型方法
        a. 聲明多了一對尖括號 + 占位符T
        b. 調用--也需要多一對尖括號,尖括號中指定的類型要和傳遞的參數的類型一致。
        c. 如果可以參數推到出類型---尖括號可以省略。
      2. 泛型方法---做到了性能高---可以一個方法滿足不同類的需求:---又讓馬兒跑,又讓馬吃草

      二、泛型的聲明

      1.泛型方法:在方法名稱后面多一對尖括號,尖括號中有占位符
      2.延遲聲明:聲明的時候,只是給一個占位符T,T是什么類型?不知道什么類型---調用的時候,指定你是什么,調用的時候,你說什么就是什么;
      3.占位符: T ---類型參數 --- 類型變量
      4.類型參數當作方法的參數的時候,明確參數類型。

      三、泛型的特點+原理 -- 底層如何支持的?

      1. 在高級語言中,定義的泛型T,在計算機執行的時候一定要是一個具體的類型。
      2. 在底層如何支持?---在底層看到,生成的結果是LIST1[T] Dictionary2[TKey,TValue]
      3. 在底層---生成了1、2、3、4、5、6
      4. 編譯器必須要能夠支持泛型
      5. CLR運行時環境也需要要支持泛型
      6. 泛型當然是框架的升級支持的---泛型不是語法糖---有框架的升級支持的;
      7. 語法糖:是編譯器提供的便捷功能。

      四、泛型的多種應用

      1. 泛型方法---可以一個方法滿足不同類型的需求
      2. 泛型接口---可以一個接口滿足不同類型的需求 --- 尖括號+占位符
      3. 泛型類-----可以一個類型滿足不同類型的需求
      4. 泛型委托---可以一個委托滿足不同類型的需求
        尖括號中可以有多個類型參數。
      public class GenericsTest
          {
              public interface GenericsInterface<T>
              {
                  public T show();
              }
              public class GenericsClass<T>
              {
                  public void Show(T t)
                  { 
                      Console.WriteLine(t); 
                  }
              }
      
              public delegate T genericsDelegate<T>();
      
              //1.泛型方法
              static void Show<T>(T value)
              {
                  Console.WriteLine(value);
              }
              
              //2.泛型接口
              GenericsInterface<string> genericsString = null;
              GenericsInterface<DateTime> genericsDatetime = null;
             
              //3.泛型類
              GenericsClass<string> genericsClassString = null;
              GenericsClass<DateTime> genericsClassDateTime = null;
      
              //4.泛型委托
              genericsDelegate<string> genericsDelegateString=null;
              genericsDelegate<DateTime> genericsDelegateDateTime=null;
      
          }
      
      

      類型參數一定要為T嗎?不一定,也可以是其他的名字(不要使用關鍵字)。
      并且尖括號中可以有多個類型參數

        public class GenericsClass<T,S,X,GODLWL>
              {
                  public void Show(T t)
                  { 
                      Console.WriteLine(t); 
                  }
              }
      
      

      繼承抽象泛型類的情況

           //使用T報錯,為什么不行?要繼承的時候,必須要確定類型,
              public abstract class Children:FatherClass<T>
              {
      
              }
            //不報錯,在子類實例化的時候,父類的類型也會被確定。
               public class Children1<S> : FatherClass<S>
              {
      
              }
      
      

      繼承類的狀況

         public class Children2<S>
              {
                  public S show()
                  {
                      return default(S); 
                  }
      
                  public S show(S s)
                  {
                      return s;
                  }
              }
      
      

      五、類型安全解讀

      要有真正的自由--就需要要有約束--開車---交通規則--紅綠燈

      1. Object類型
       public class Genericconstraints
          {
      
              public class People
              {
                  public int Id { get; set; }
                  public string Name { get; set; }  
              }
              public static void ShowObject(object oValue)
              {
                  //沒有意義的打印輸出
                  //Console.WriteLine(oValue);
                  //傳遞一個實體的對象:操作字段和方法
                  //問題:
                  //1.無法去屬性字段--因為oValue是Object;C#是強類型語言,編譯時決定參數是什么類型;
                  //Console.WriteLine($"People.Id={oValue.Id}");
                  //Console.WriteLine($"People.Name={oValue.Name}");
                  //2、強制轉換
                  People people = (People)oValue;
                  Console.WriteLine($"People.Id={people.Id}");
                  Console.WriteLine($"People.Name={people.Name}");
              }
          }
      

      當我們傳遞一個INT類型的變量的時候,運行的時候就會報錯。
      為了避免這種類型安全的問題,我們就引入了泛型的約束。

      六、泛型的約束

      1. 如何避免泛型的類型安全問題,引入了泛型約束。
       //基類約束
              //a.就是把類型參數當做People
              //b.調用---就可以傳遞People或者People的子類型
              //c.泛型約束:要么不讓你進來;如果讓你進來,就一定是沒問題的
              public static void Show<T>(T tValue) where T : People
              {
                  Console.WriteLine($"People.Id={tValue.Id}");
                  Console.WriteLine($"People.Name={tValue.Name}");
              }
          public interface ISports
              {
                  public void run();
              }
              public class Cat:ISports
              {
                  public void run()
                  {
                      Console.WriteLine("Cat run");
                  }
              }
              //接口約束
              // a.把這個T當做ISports
              // b.就只能傳遞ISports這個接口或者實現這個接口的類
              // c.就可以增加功能,也可以獲取新的功能。
              public static void ShowInterface<T>(T tValue) where T : ISports
              {
                  tValue.run();
              }
      
        //引用類型約束
              // a.就只能傳遞類型進來
              public static void ShowClass<T>(T tValue) where T : class
              {
                  
              }
      
         //值類型約束
              // a.只能傳遞值類型進來
              public static void ShowValue<T>(T tValue) where T : struct
              {
      
              }
      
          //無參數構造函數約束
              //
              public static void ShowNew<T>(T tValue) where T : new()
              {
                  T t= new T();
              }
      
            //枚舉約束
              public static void ShowEnum<T>(T tValue) where T : Enum
              {
      
              }
      

      七、泛型緩存---泛型類

      泛型緩存可以根據不同的類型生成一個新的類的副本;生成無數個副本;

       public class GenericCacheTest
          {
              public static void Show()
              {
      
                  //普通緩存
                  {
                      for (int i = 0; i < 5; i++)
                      {
                          Console.WriteLine(DictionaryCache.GetCache<int>()); //GenericCacheInt
                          Thread.Sleep(10);
                          Console.WriteLine(DictionaryCache.GetCache<long>());// GenericCachelong
                          Thread.Sleep(10);
                          Console.WriteLine(DictionaryCache.GetCache<DateTime>());
                          Thread.Sleep(10);
                          Console.WriteLine(DictionaryCache.GetCache<string>());
                          Thread.Sleep(10);
                          Console.WriteLine(DictionaryCache.GetCache<GenericCacheTest>());
                          Thread.Sleep(10);
                      }
                  }
      
                  //泛型緩存
                  {
                      for (int i = 0; i < 5; i++)
                      {
                          Console.WriteLine(GenericCache<int>.GetCache()); //GenericCacheInt
                          Thread.Sleep(10);
                          Console.WriteLine(GenericCache<long>.GetCache());// GenericCachelong
                          Thread.Sleep(10);
                          Console.WriteLine(GenericCache<DateTime>.GetCache());
                          Thread.Sleep(10);
                          Console.WriteLine(GenericCache<string>.GetCache());
                          Thread.Sleep(10);
                          Console.WriteLine(GenericCache<GenericCacheTest>.GetCache());
                          Thread.Sleep(10);
                      }
                  }
              }
          }
      
          /// <summary>
          /// 字典緩存:靜態屬性常駐內存
          /// </summary>
          public class DictionaryCache
          {
              private static Dictionary<Type, string> _TypeTimeDictionary = null;
      
              //靜態構造函數在整個進程中,執行且只執行一次;
              static DictionaryCache()
              {
                  Console.WriteLine("This is DictionaryCache 靜態構造函數");
                  _TypeTimeDictionary = new Dictionary<Type, string>();
              }
              public static string GetCache<T>()
              {
                  Type type = typeof(T);
                  if (!_TypeTimeDictionary.ContainsKey(type))
                  {
                      _TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
                  }
                  return _TypeTimeDictionary[type];
              }
          }
      
      
          /// <summary>
          ///泛型緩存:
          /// </summary>
          /// <typeparam name="T"></typeparam>
          public class GenericCache<T>
          {
              static GenericCache()
              {
                  Console.WriteLine("This is GenericCache 靜態構造函數");
                  //_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff")); 
                  _TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
              }
      
              private static string _TypeTime = "";
      
              public static string GetCache()
              {
                  return _TypeTime;
              }
      
          }
      

      七、泛型的協變和逆變

      比如我們有一個動物類以及它的子類貓類

          public class Animal
          {
              public int Id { get; set; }
      
          }
      
          public class Cat : Animal {
              public string Name { get; set; }
          }
      

      我們可以使用這樣的代碼

      //任何子類都可以使用父類來聲明
      Animal animal1 = new Cat();
      //不一定能用子類來聲明父類
      Cat cat2 = new Animal();
      
      

      我們還會遇到這樣的問題
      一只貓是一堆動物
      一堆貓卻不是一堆動物---從口語上來說,有點不符合人類的邏輯的思維。

      List<Animal> animals = new List<Animal>();
      //報錯
      List<Animal> animals2 = new List<Cat>();
      

      為什么?---二類沒有父子級關系;當然不能替換;這是C#語法所決定的。
      泛型存在不友好,不協調的地方;

      這樣就引入我們的協變和逆變;
      協變逆變 只針對于泛型接口和泛型委托

      //協變 就可以讓右邊使用子類,能讓左邊用父類
      //out:修飾類型參數:就可以讓右邊用子類,能讓左邊用父類
      IEnumerable<Animal> animals1=new List<Animal>();
      IEnumerable<Animal> animals3= new List<Cat>();
      

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

      逆變In 只能做參數,不能做返回值

       public interface ICustomerListIn<in T>
          {
              void show(T t);
          }
      
          public class CustomerListIn<T>:ICustomerListIn<T>
          {
              public void show(T t)
              {
      
              }
          }
      

      逆變的代碼例子

      //逆變:就可以讓右邊用父類;左邊用子類;
      ICustomerListIn<Cat> customerListIn = new CustomerListIn<Animal>();
      ICustomerListIn<Cat> customerListIn1 = new CustomerListIn<Cat>();
      

      為什么要有協變和逆變?
      如果沒有協變和逆變會怎么樣?

      
       public interface ICustomerList<T> {
              T Get();
      
              void show(T t);
          }
      
          public class CustomerList<T>:ICustomerList<T>
          {
              public T Get()
              {
                  return default(T);
              }
              public void show(T t)
              {
      
              }
          }
      
      }
      
      ICustomerList<Animal> customerList=new CustomerList<Animal>();
      ICustomerList<Animal> customerList1 = new CustomerList<Cat>();
      
      

      泛型的協變和逆變更像是一種高級約束,是為規避

      1. 把子類做參數,卻把父類當參數傳入;
      2. 把子類做返回值,卻在返回的時候,返回了一個父類。
      posted @ 2023-03-24 13:32  飄雨的河  閱讀(156)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产高潮国产高潮久久久| 亚洲成人av在线综合| 久久久久无码中| 蜜桃一区二区三区在线看| 福利视频一区二区在线| 青青草无码免费一二三区| 蜜桃一区二区三区在线看| 成人3d动漫一区二区三区| 亚洲中文字幕无码日韩精品| 无码抽搐高潮喷水流白浆| 亚洲AV无码国产在丝袜APP| 亚洲乱码精品中文字幕| 囯产精品久久久久久久久久妞妞 | 亚洲无线码一区在线观看| 色欲国产精品一区成人精品| 日韩精品一区二区三区不卡| 人妻系列无码专区久久五月天| 黑人强伦姧人妻久久| 亚洲欧美日韩综合久久| 免费国产拍久久受拍久久| 99精品久久久久久久婷婷| 九九热在线观看视频免费| 天天弄天天模| 日韩中文字幕亚洲精品一| 蜜臀久久综合一本av| 亚洲成av人片在www鸭子| 精品久久久久久亚洲综合网| 国产小受被做到哭咬床单GV| 人妻一区二区三区三区| 你懂的在线视频一区二区| 国产人妻人伦精品1国产丝袜| 日韩av不卡一区二区在线| 狠狠五月深爱婷婷网| 久久亚洲av成人无码软件| 91麻豆亚洲国产成人久久| 女高中生自慰污污网站| 日本中文一区二区三区亚洲| 国产精品女在线观看| 国产精品无码av不卡| 日韩美女视频一区二区三区| 亚洲综合另类小说色区一|