.NET知識梳理——1.泛型Generic

来源:https://www.cnblogs.com/Olive116/archive/2020/02/20/12334767.html

1. 泛型Generic 1.1 引入泛型:延遲聲明 泛型方法聲明時,並未寫死類型,在調用的時候再指定類型。 延遲聲明:推遲一切可以推遲的。 1.2 如何聲明和使用泛型 泛型方法:方法名稱後面加上尖括弧,裡面是類型參數 類型參數實際上就是一個類型T聲明,方法就可以用這個類型T了。 如下所示: pub ...


1. 泛型Generic

1.1        引入泛型:延遲聲明

泛型方法聲明時,並未寫死類型,在調用的時候再指定類型。

延遲聲明:推遲一切可以推遲的。

1.2        如何聲明和使用泛型

泛型方法:方法名稱後面加上尖括弧,裡面是類型參數

類型參數實際上就是一個類型T聲明,方法就可以用這個類型T了。

如下所示:

public static void Show<T>(T t)

        {

            Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");

        }

1.3        泛型的好處和原理

泛型方法性能跟普通方法一致,泛型聲明方法時,並未寫死類型,T是什麼類型,只有在調用的時候才知道,一個方法能滿足不同類型。

1.4        泛型類、泛型方法、泛型介面、泛型委托

1.4.1  泛型類型

一個類滿足不同類型的需求

具體如下:

public class BaseModel

    {

        public int Id { get; set; }

    }

    public class GenericClass<T>

        where T:BaseModel//為泛型基類約束

    {

 

    }

1.4.2  泛型方法

一個方法滿足不同類型的需求

具體如下:

public static void Show<T>(T t)

        {

            Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");

        }

1.4.3  泛型介面

一個介面滿足不同類型的需求

   //泛型介面

    public interface IGenericInterface<T>

    {

        public void  SayHi(T t);

}

1.4.4  泛型委托

一個委托滿足不同類型的需求

public delegate void Do<T>(T t);

1.5        泛型約束

沒有約束,泛型會很局限。主要有5中泛型的約束。如下:

1.5.1  基類約束

Where T:BaseModel

可以把BaseModel當作基類

只有該類型的對象或從該類型派生出的對象,可被用作類型參數。(密封類約束的不行,因為沒有意義。)

//基類

    public class BaseModel

    {

        public int Id { get; set; }

    }

    //泛型類

    public class GenericClass<T>

        where T:BaseModel//為泛型基類約束

    {

 

}

調用:

  GenericConstraint.Show<BeiJing>(new BeiJing());

1.5.2  引用類型約束

 

//引用類型約束

        public static T Get<T>() where T:class

        {

            return default(T);//default是關鍵字,根據類型T返回對應的預設值

        }

調用:

GenericConstraint.Get<Person>(new Person());

1.5.3  值類型約束

 

  //值類型約束

        Public static D GetD<D>() where D:struct

        {

            return default(D);

        }

調用:

GenericConstraint.GetD<int>(116);

1.5.4  無參數構造函數

 

//無參數構造函數約束

        Public static S GetS<S>()

            where S: new()//無餐構造函數約束

        {     

            return new S();

        }

調用:

GenericConstraint.GetS<Chinese>();

1.5.5  介面約束

 

//介面約束

        public static void Show2<T>(T t) where T : ISports

        {

            t.Basketball();

        }

調用:

GenericConstraint.Show2<USA>(new USA());

1.6        協變、逆變

所謂協變、逆變都是跟泛型有關的(多用在介面)。

1.6.1  協變

修飾返回值

讓右邊用子類,讓泛型用起來更方便(子類轉父類)

Out修飾,協變後只能是返回結果,不能做參數

IEnumerable<Bird> birdList=new List<Sparrow>();

  //out 協變,只能是返回結果(子類轉父類)

    public interface ICustomerListOut<out T>

    {

        T Get();

    }

 

    public class CustomerListOut<T>:ICustomerListOut<T>

    {

        public T Get()

        {

            return default(T);

        }

}

 

ICustomerListOut<Bird> list2 = new CustomerListOut<Sparrow>();

            Func<Bird> func = new Func<Sparrow>(() => null);

            IEnumerable<Bird> list3 = new List<Sparrow>();

1.6.2  逆變

修飾傳入參數

讓右邊可以用父類,讓泛型用起來更方便(父類轉子類)

In修飾,逆變後只能當作參數

//in 逆變 只能是輸入參數(父類轉子類)

    public interface ICustomerListIn<in T>

    {

        void Show(T t);

    }

    public class CustomerListIn<T>:ICustomerListIn<T>

    {

        public void Show(T t)

        {

            Console.WriteLine(t.GetType().Name);

        }

}

  //逆變

            ICustomerListIn<Sparrow> list1 = new CustomerListIn<Bird>();

            Action<Sparrow> action = new Action<Bird>((i) => { });

 

public interface IMyList<in inT,out outT>

    {

        void Show(inT t);

        outT Get();

        outT Do(inT t);

    }

 

    public class MyList<T, T1> : IMyList<T, T1>

    {

        public void Show(T t)

        {

            Console.WriteLine(t.GetType().Name);

        }

 

        public T1 Get()

        {

            Console.WriteLine(typeof(T1).Name);

            return default(T1);

        }

 

        public T1 Do(T t)

        {

            Console.WriteLine(t.GetType().Name);

            Console.WriteLine(typeof(T1).Name);

            return default(T1);

        }

    }

   IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>();

    IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>();//協變

    IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>();//逆變

IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>();//逆變+協變

1.7        泛型緩存

泛型緩存,每個類型都會生成一個不同的副本(適合不同類型需要緩存一份數據的場景)

  public class GenericCache<T>

    {

        private static string _TypeTime = "";

        static GenericCache()

        {

            Console.WriteLine("This is GenericCache 靜態構造函數");

            _TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";

        }

 

        public static string GetCache()

        {

            return _TypeTime;

        }

}

 

/// <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(Type);

            if (!_TypeTimeDictionary.ContainsKey(type))

                _TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH mm:ss")}";

            return _TypeTimeDictionary[type];

        }

    }


您的分享是我們最大的動力!

更多相關文章
  • 擱置了幾天,工作忙的一塌糊塗,今天終於抽空來繼續看看MVC的知識。先來看看MVC的路由是如何處理的。以下為替代的路由: app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{ ...
  • 前言 通常在應用程式開發到正式上線,在這個過程中我們會分為多個階段,通常會有 開發、測試、以及正式環境等。每個環境的參數配置我們會使用不同的參數,因此呢,在ASP.NET Core中就提供了相關的環境API,方便我們更好的去做這些事情。 環境 ASP.NET Core使用ASPNETCORE_ENV ...
  • ​ 在C#8.0中,針對介面引入了一項新特性,就是可以指定預設實現,方便對已有實現進行擴展,也對面向Android和Swift的Api進行互操作提供了可能性。下麵我們來看看該特性的具體規則與實現。 一、主要應用場景: 在不破壞影響已有實現的情況下,可以添加新成員。這解決了在第三方已經大量使用了的介面 ...
  • 一文帶你瞭解 C DLR 的世界 在很久之前,我寫了一片文章 "dynamic結合匿名類型 匿名對象傳參" ,裡面我以為DLR內部是用反射實現的。因為那時候是心中想當然的認為只有反射能夠在運行時解析對象的成員信息並調用成員方法。後來也是因為其他的事一直都沒有回過頭來把這一節知識給補上,正所謂亡羊補牢 ...
  • 首先新建一個項目,名稱叫Caliburn.Micro.ActionConvertions 然後刪掉MainWindow.xaml 然後去app.xaml刪掉StartupUri這行代碼 其次,安裝Caliburn.Micro,Caliburn.Micro.Core,這兩個Nuget包,如下圖 然後新 ...
  • 先看核心代碼: public List<DataEntity> SearchShopSalesReport(DateTimeOffset? dateFrom, DateTimeOffset? dateTo,string groupBy) { var query = data.DataEntity / ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7928521.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第四個模式--觀察者模式,先從名字上來看。觀察者模式可以理解為既然有“觀察者”,那肯定就有“被觀察者”了。“觀察者” ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7903617.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第三個模式--迭代器模式,先從名字上來看。迭代是遍歷的意思,迭代器可以理解為是遍歷某某的工具,遍歷什麼呢?在軟 件設 ...
一周排行
  • 一、引言 按照專用隊列解釋: MachineName\Private$\QueueName,只針對於本機的程式才可以調用的隊列,有些情況下為了安全起見定義為私有隊列。所以剛開始的時候認為,要想訪問遠程消息隊列,只能使用公共隊列。但是後來發現,公共隊列依賴Domain Controller(域控),在 ...
  • 本文只對api介面,header請求參數進行簡單驗證,起到拋磚引玉使用,需要深入驗證,請自行擴展 項目目錄結構如圖 中間件類 using ApiMiddleware.Common.DataEnityModel; using ApiMiddleware.Common.DbContext; using ...
  • 前言:由於公司占時沒有運維,出於微服務的需要,Apollo只能先裝在windows 阿裡雲上跑起來,由於環境及網路等問題,在安裝過程中遇到很多坑,算是一個個坑填完後,最終實現。 一. java jdk環境 java jdk 1.8下載地址: https://www.oracle.com/java/t ...
  • 前言 nuget 是 .net 的常用包管理器,目前已經內置到 Visual Studio 2012 以後的版本。大多數 .net 包都托管在 nuget.org,包括 .net core 框架基礎包,得益於 .net core 的模塊化設計,很多非核心包都可以進行一定程度的獨立升級。 製作並上傳 ...
  • 簡單的介紹一下集合,通俗來講就是用來保管多個數據的方案。比如說我們是一個公司的倉庫管理,公司有一堆貨物需要管理,有同類的,有不同類的,總而言之就是很多、很亂。我們對照集合的概念對倉庫進行管理的話,那麼 數組就是將一堆貨整整齊齊的碼在倉庫的某個地方,普通列表也是如此;Set就是在倉庫里有這麼一個貨架, ...
  • 中間件分類 ASP.NET Core 中間件的配置方法可以分為以上三種,對應的Helper方法分別是:Run(), Use(), Map()。 Run(),使用Run調用中間件的時候,會直接返回一個響應,所以後續的中間件將不會被執行了。 Use(),它會對請求做一些工作或處理,例如添加一些請求的上下 ...
  • 字元串的常用操作 很好理解 字元串可以用 ' + ' 連接,或者乘一個常數重覆輸出字元串 字元串的索引操作 通過一對中括弧可以找到字元串中的某個字元 可以通過正負數雙向操作噢 用一個中括弧來實現 為什麼沒有-0??去清醒腦子想想 -0 和 0 有差嗎? 還有一個切片操作 就像切菜那樣簡單,同樣是中括 ...
  • title: Java基礎語法(3) 運算符 blog: "CSDN" data: "Java學習路線及視頻" 1.算術運算符 算術運算符的註意問題 如果對負數取模,可以把模數負號忽略不記,如:5% 2=1。 但被模數是負數則不可忽略。此外,取模運算的結果不一定總是整數。 對於除號“/”,它的整數除 ...
  • 下麵是互相轉換的代碼: 有想要瞭解更多關於python知識的請在下方評論或私信小編 ...
  • 引言 構建分散式系統並不容易。然而,人們日常所使用的應用大多基於分散式系統,在短時間內依賴於分散式系統的現狀並不會改變。ApacheZooKeeper旨在減輕構建健壯的分散式系統的任務。ZooKeeper基於 分散式計算的核心概念而設計,主要目的是給開發人員提供一套容易理解和開發的介面,從而簡化分佈 ...
x