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

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

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];

        }

    }


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

-Advertisement-
Play Games
更多相關文章
  • 擱置了幾天,工作忙的一塌糊塗,今天終於抽空來繼續看看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,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第三個模式--迭代器模式,先從名字上來看。迭代是遍歷的意思,迭代器可以理解為是遍歷某某的工具,遍歷什麼呢?在軟 件設 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...