泛型的原理、應用、約束、緩存

什麼是泛型

泛型是程序設計語言的一種特性。容許程序員在強類型程序設計語言中編寫代碼時定義一些可變部分,那些部分在使用前必須做出指明。各類程序設計語言和其編譯器、運行環境對泛型的支持均不同。將類型參數化以達到代碼複用提升軟件開發工做效率的一種數據類型。泛型類是引用類型,是堆對象,主要是引入了類型參數這個概念。程序員

.net framework1.0時代,若是有如下需求,須要傳遞不一樣類型變量的值,而且打印該變量的值。express

  • 定義多個不一樣類型參數的方法:(重複代碼量大、開發成本高、難以應對複雜的業務需求,微軟考慮到這些問題,在.net framework2.0推出了泛型)
 1         /// <summary>
 2         /// 打印個int值
 3         /// </summary>
 4         /// <param name="iParameter"></param>
 5         public static void ShowInt(int iParameter)
 6         {
 7             Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
 8         }
 9         /// <summary>
10         /// 打印個string值
11         /// </summary>
12         /// <param name="sParameter"></param>
13         public static void ShowString(string sParameter)
14         {
15             Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
16         }
17         /// <summary>
18         /// 打印個DateTime值
19         /// </summary>
20         /// <param name="oParameter"></param>
21         public static void ShowDateTime(DateTime dtParameter)
22         {
23             Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
24         }
  • 定義一個Object類型(沒有約束,任何類型都能傳遞進來,因此可能不安全)
 1         /// <summary>
 2         /// 打印個object值
 3         /// 1 任何父類出現的地方,均可以用子類來代替,object是一切類型的父類
 4         /// 2 使用Object產生兩個問題:裝箱拆箱、類型安全
 5         /// </summary>
 6         /// <param name="oParameter"></param>
 7         public static void ShowObject(object oParameter)
 8         {
 9             Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod), oParameter.GetType().Name, oParameter);
10         }
  • object類型參數有兩個問題:
  1. 裝箱拆箱,性能損耗,傳入一個int值(棧),object又在堆裏面,若是把int傳遞進來,就會把值從棧裏面copy到堆裏,使用的時候,又須要用對象值,又會copy到棧(拆箱)
  2. 類型安全問題,可能會有,由於傳遞的對象是沒有限制的
  • 使用泛型方法
1         /// <summary>
2         /// 泛型方法
3         /// </summary>
4         /// <typeparam name="T"></typeparam>
5         /// <param name="tParameter"></param>
6         public static void Show<T>(T tParameter)//, T t = default(T
7         {
8             Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod), tParameter.GetType().Name, tParameter);
9         }
  • 泛型方法:

   方法名稱後面加上尖括號,<>裏面是類型參數,類型參數實際上就是一個不肯定類型T聲明,聲明事後方法就能夠用這個不肯定類型T了。在聲明泛型時,並無寫死類型,T是什麼?不知道,T要等着調用的時候才指定。正是由於沒有寫死,才擁有了無限的可能!!編程

  • 泛型的設計思想:

  延遲聲明:推遲一切能夠推遲的,一切能晚點再作的事兒,就晚點再作。深刻一下,泛型的原理,泛型在代碼編譯時,究竟生成了一個什麼東西?泛型不是一個簡單的語法糖,是框架升級支持的。泛型方法的性能跟普通方法一致,是最好的,並且還能一個方法知足多個不一樣類型。緩存

泛型的定義主要有如下兩種:

1.在程序編碼中一些包含類型參數的類型,也就是說泛型的參數只能夠表明類,不能表明個別對象。(這是當今較常見的定義)安全

2.在程序編碼中一些包含參數的類。其參數能夠表明類或對象等等。(人們大多把這稱做模板)不論使用哪一個定義,泛型的參數在真正使用泛型時都必須做出指明。框架

一些強類型編程語言支持泛型,其主要目的是增強類型安全及減小類轉換的次數,但一些支持泛型的編程語言只能達到部分目的。編程語言

.NET Framework 的泛型

泛型是具備佔位符(類型參數)的類、結構、接口和方法,這些佔位符是類、結構、接口和方法所存儲或使用的一個或多個類型的佔位符。泛型集合類能夠將類型參數用做它所存儲的對象的類型的佔位符;類型參數做爲其字段的類型及其方法的參數類型出現。泛型方法能夠將其類型參數用做其返回值的類型或者其某個形參的類型。函數

因爲.NET Framework 泛型的類型參數之實際類型在運行時均不會被消除,運行速度會由於類型轉換的次數減小而加快。性能

1                 Console.WriteLine(typeof(List<>));
2                 Console.WriteLine(typeof(Dictionary<,>));

打印結果:編碼

.NET泛型的使用:

  • 泛型方法:爲了一個方法知足不一樣的類型的需求,爲了一個方法知足不一樣的類型的需求,一個方法完成多實體的查詢,一個方法完成不一樣的類型的數據展現。
 1         public List<T> GetList<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class, new()
 2         {
 3             SqlSugarClient ssc = new SugarHelper(ConnectionKey).GetSqlSugarClient();
 4             List<T> t = ssc.Queryable<T>().Where(expression).ToList();
 5             if (t != null && t.Count > 0)
 6             {
 7                 return t;
 8             }
 9             return null;
10         }
  • 泛型類:一個類,知足不一樣類型的需求
  • 泛型接口:一個接口,知足不一樣類型的需求
    public interface GenericInterface<T>
    {
}
  • 泛型委託:一個委託,知足不一樣類型的需求,如.Net自帶的Action和Fucn
  • 任意一個實體,轉換成一個JSON字符串。

泛型約束

  容許對個別泛型的類型參數進行約束,包括如下幾種形式(假設 C是泛型的類型參數, 是通常類、泛類,或是泛型的類型參數):T 是一個類。T 是一個值類型。T 具備無參數的公有建構方法。T 實現接口 I 。T 是 C ,或繼承自 C 。

  沒有約束,其實很受侷限,自由主義的鼻祖洛克先生說過,有了法律,纔有自由,其實自由都是相對的。基類約束:where T:BaseModel能夠把T當成基類,T必須是BaseModel或者其子類。爲何要有約束?Eg:紅綠燈約束,綠燈行(權利)、紅燈停(約束),由於有約束纔有綠燈行的權利。

示例:

  • 基類約束
      public class People
      {
          public int Id { get; set; }
          public string Name { get; set; }
          public void Hi()
          { }
      }
        /// <summary>
        /// 基類約束,T必須是People或People的子類
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void Show<T>(T tParameter)where T:People
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",typeof(GenericConstraint), tParameter.GetType().Name, tParameter);
            Console.WriteLine($"{tParameter.Id}  {tParameter.Name}");
            tParameter.Hi();
        }
  • 引用類型約束
1         /// <summary>
2         /// 引用類型約束,T必須是一個引用類型
3         /// </summary>
4         /// <typeparam name="T"></typeparam>
5         /// <returns></returns>
6         public T GetT<T>() where T : class
7         {
8             return null;
9         }
  • 值類型約束
1         /// <summary>
2         /// 值類型約束
3         /// </summary>
4         /// <typeparam name="T"></typeparam>
5         /// <returns></returns>
6         public T ShowT<T>() where T : struct
7         {
8             return default(T); //default是個關鍵字,會根據T的類型去得到一個默認值
9         }
  • 無參數構造函數約束
 1         /// <summary>
 2         /// 無參數構造函數
 3         /// </summary>
 4         /// <typeparam name="T"></typeparam>
 5         /// <typeparam name="S"></typeparam>
 6         /// <returns></returns>
 7         public T GetT<T, S>() where T : new()
 8         {
 9             return new T();
10         }
  • 多個約束
 1         /// <summary>
 2         /// 多個約束
 3         /// </summary>
 4         /// <typeparam name="T"></typeparam>
 5         /// <typeparam name="S"></typeparam>
 6         /// <returns></returns>
 7         public T GetT_<T, S>()
 8            where T : People, IWork, new()
 9         {
10             return new T();
11         }
  • 多個參數一致性約束
 1         /// <summary>
 2         /// 多個參數一致性約束,表示T和S都必須是People或People的子類
 3         /// </summary>
 4         /// <typeparam name="T"></typeparam>
 5         /// <typeparam name="S"></typeparam>
 6         /// <returns></returns>
 7         public T FindT<T, S>() where T : People where S : T
 8         {
 9             return null;
10         }

ps:不能使用密封類約束,由於沒有意義。

泛型緩存

  每一個不一樣的T,都會生成一份不一樣的副本,適合不一樣類型,須要緩存一份數據的場景,效率高。

 1     /// <summary>
 2     /// 每一個不一樣的T,都會生成一份不一樣的副本,適合不一樣類型,須要緩存一份數據的場景,效率高。
 3     /// </summary>
 4     /// <typeparam name="T"></typeparam>
 5     public class GenericCache<T>
 6     {
 7         static GenericCache()
 8         {
 9             Console.WriteLine("This is GenericCache 靜態構造函數");
10             _TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
11         }
12         private static string _TypeTime = "";
13         public static string GetCache()
14         {
15             return _TypeTime;
16         }
17     }
相關文章
相關標籤/搜索