国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

C#泛型的用法及實(shí)例詳解

發(fā)布時(shí)間:2021-09-04 11:55 來(lái)源:億速云 閱讀:0 作者:chen 欄目: 開(kāi)發(fā)技術(shù)

這篇文章主要講解了“C#泛型的用法及實(shí)例詳解”,文中的講解內容簡(jiǎn)單清晰,易于學(xué)習與理解,下面請大家跟著(zhù)小編的思路慢慢深入,一起來(lái)研究和學(xué)習“C#泛型的用法及實(shí)例詳解”吧!

目錄
  • 一、什么是泛型

  • 二、為什么使用泛型

  • 三、泛型類(lèi)型參數

  • 四、泛型類(lèi)

  • 五、泛型約束

  • 六、泛型的協(xié)變和逆變

  • 七、泛型緩存

這篇文章主要講解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建項目框架的時(shí)候。

一、什么是泛型

泛型是C#2.0推出的新語(yǔ)法,不是語(yǔ)法糖,而是2.0由框架升級提供的功能。

我們在編程程序時(shí),經(jīng)常會(huì )遇到功能非常相似的模塊,只是它們處理的數據不一樣。但我們沒(méi)有辦法,只能分別寫(xiě)多個(gè)方法來(lái)處理不同的數據類(lèi)型。這個(gè)時(shí)候,那么問(wèn)題來(lái)了,有沒(méi)有一種辦法,用同一個(gè)方法來(lái)處理傳入不同種類(lèi)型參數的辦法呢?泛型的出現就是專(zhuān)門(mén)來(lái)解決這個(gè)問(wèn)題的。

二、為什么使用泛型

先來(lái)看下面一個(gè)例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class CommonMethod
    {
        /// <summary>
        /// 打印個(gè)int值
        /// </summary>
        /// <param name="iParameter"></param>
        public static void ShowInt(int iParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
        }

        /// <summary>
        /// 打印個(gè)string值
        /// </summary>
        /// <param name="sParameter"></param>
        public static void ShowString(string sParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
        }

        /// <summary>
        /// 打印個(gè)DateTime值
        /// </summary>
        /// <param name="oParameter"></param>
        public static void ShowDateTime(DateTime dtParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
        }
    }
}

結果:

從上面的結果中我們可以看出這三個(gè)方法,除了傳入的參數不同外,其里面實(shí)現的功能都是一樣的。在1.0版的時(shí)候,還沒(méi)有泛型這個(gè)概念,那么怎么辦呢。相信很多人會(huì )想到了OOP三大特性之一的繼承,我們知道,C#語(yǔ)言中,object是所有類(lèi)型的基類(lèi),將上面的代碼進(jìn)行以下優(yōu)化:

public static void ShowObject(object oParameter)
{
      Console.WriteLine("This is {0},parameter={1},type={2}",
         typeof(CommonMethod), oParameter.GetType().Name, oParameter);
}

結果:

從上面的結果中我們可以看出,使用Object類(lèi)型達到了我們的要求,解決了代碼的可復用??赡苡腥藭?huì )問(wèn)定義的是object類(lèi)型的,為什么可以傳入int、string等類(lèi)型呢?原因有二:

1、object類(lèi)型是一切類(lèi)型的父類(lèi)。

2、通過(guò)繼承,子類(lèi)擁有父類(lèi)的一切屬性和行為,任何父類(lèi)出現的地方,都可以用子類(lèi)來(lái)代替。

但是上面object類(lèi)型的方法又會(huì )帶來(lái)另外一個(gè)問(wèn)題:裝箱和拆箱,會(huì )損耗程序的性能。

微軟在C#2.0的時(shí)候推出了泛型,可以很好的解決上面的問(wèn)題。

三、泛型類(lèi)型參數

在泛型類(lèi)型或方法定義中,類(lèi)型參數是在其實(shí)例化泛型類(lèi)型的一個(gè)變量時(shí),客戶(hù)端指定的特定類(lèi)型的占位符。 泛型類(lèi)(GenericList<T>)無(wú)法按原樣使用,因為它不是真正的類(lèi)型;它更像是類(lèi)型的藍圖。 若要使用GenericList<T>,客戶(hù)端代碼必須通過(guò)指定尖括號內的類(lèi)型參數來(lái)聲明并實(shí)例化構造類(lèi)型。 此特定類(lèi)的類(lèi)型參數可以是編譯器可識別的任何類(lèi)型。 可創(chuàng )建任意數量的構造類(lèi)型實(shí)例,其中每個(gè)使用不同的類(lèi)型參數。

上面例子中的代碼可以修改如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class GenericMethod
    {
        /// <summary>
        /// 泛型方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void Show<T>(T tParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
        }
    }
}

調用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    class Program
    {
        static void Main(string[] args)
        {

            int iValue = 123;
            string sValue = "456";
            DateTime dtValue = DateTime.Now;

            Console.WriteLine("***********CommonMethod***************");
            CommonMethod.ShowInt(iValue);
            CommonMethod.ShowString(sValue);
            CommonMethod.ShowDateTime(dtValue);
            Console.WriteLine("***********Object***************");
            CommonMethod.ShowObject(iValue);
            CommonMethod.ShowObject(sValue);
            CommonMethod.ShowObject(dtValue);
            Console.WriteLine("***********Generic***************");
            GenericMethod.Show<int>(iValue);
            GenericMethod.Show<string>(sValue);
            GenericMethod.Show<DateTime>(dtValue);
            Console.ReadKey();
        }
    }
}

顯示結果:

為什么泛型可以解決上面的問(wèn)題呢?

泛型是延遲聲明的:即定義的時(shí)候沒(méi)有指定具體的參數類(lèi)型,把參數類(lèi)型的聲明推遲到了調用的時(shí)候才指定參數類(lèi)型。 延遲思想在程序架構設計的時(shí)候很受歡迎。例如:分布式緩存隊列、EF的延遲加載等等。

泛型究竟是如何工作的呢?

控制臺程序最終會(huì )編譯成一個(gè)exe程序,exe被點(diǎn)擊的時(shí)候,會(huì )經(jīng)過(guò)JIT(即時(shí)編譯器)的編譯,最終生成二進(jìn)制代碼,才能被計算機執行。泛型加入到語(yǔ)法以后,VS自帶的編譯器又做了升級,升級之后編譯時(shí)遇到泛型,會(huì )做特殊的處理:生成占位符。再次經(jīng)過(guò)JIT編譯的時(shí)候,會(huì )把上面編譯生成的占位符替換成具體的數據類(lèi)型。請看下面一個(gè)例子:

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

結果:

從上面的截圖中可以看出:泛型在編譯之后會(huì )生成占位符。

注意:占位符需要在英文輸入法狀態(tài)下才能輸入,只需要按一次波浪線(xiàn)(數字1左邊的鍵位)的鍵位即可,不需要按Shift鍵。

1、泛型性能問(wèn)題

請看一下的一個(gè)例子,比較普通方法、Object參數類(lèi)型的方法、泛型方法的性能。

添加一個(gè)Monitor類(lèi),讓三種方法執行同樣的操作,比較用時(shí)長(cháng)短:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class Monitor
    {
        public static void Show()
        {
            Console.WriteLine("****************Monitor******************");
            {
                int iValue = 12345;
                long commonSecond = 0;
                long objectSecond = 0;
                long genericSecond = 0;

                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    for (int i = 0; i < 100000000; i++)
                    {
                        ShowInt(iValue);
                    }
                    watch.Stop();
                    commonSecond = watch.ElapsedMilliseconds;
                }
                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    for (int i = 0; i < 100000000; i++)
                    {
                        ShowObject(iValue);
                    }
                    watch.Stop();
                    objectSecond = watch.ElapsedMilliseconds;
                }
                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    for (int i = 0; i < 100000000; i++)
                    {
                        Show<int>(iValue);
                    }
                    watch.Stop();
                    genericSecond = watch.ElapsedMilliseconds;
                }
                Console.WriteLine("commonSecond={0},objectSecond={1},genericSecond={2}"
                    , commonSecond, objectSecond, genericSecond);
            }
        }

        #region PrivateMethod
        private static void ShowInt(int iParameter)
        {
            //do nothing
        }
        private static void ShowObject(object oParameter)
        {
            //do nothing
        }
        private static void Show<T>(T tParameter)
        {
            //do nothing
        }
        #endregion

    }
}

Main()方法調用:

Monitor.Show();

結果:

從結果中可以看出:泛型方法的性能最高,其次是普通方法,object方法的性能最低。

四、泛型類(lèi)

除了方法可以是泛型以外,類(lèi)也可以是泛型的,例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    /// <summary>
    /// 泛型類(lèi)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class GenericClass<T>
    {
        public T _T;
    }
}

Main()方法中調用:

// T是int類(lèi)型
GenericClass<int> genericInt = new GenericClass<int>();
genericInt._T = 123;
// T是string類(lèi)型
GenericClass<string> genericString = new GenericClass<string>();
genericString._T = "123";

除了可以有泛型類(lèi),也可以有泛型接口,例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    /// <summary>
    /// 泛型接口
    /// </summary>
    public interface IGenericInterface<T>
    {
        //泛型類(lèi)型的返回值
        T GetT(T t);
    }
}

也可以有泛型委托:

public delegate void SayHi<T>(T t);//泛型委托

注意:

1、泛型在聲明的時(shí)候可以不指定具體的類(lèi)型,但是在使用的時(shí)候必須指定具體類(lèi)型,例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    /// <summary>
    /// 使用泛型的時(shí)候必須指定具體類(lèi)型,
    /// 這里的具體類(lèi)型是int
    /// </summary>
    public class CommonClass :GenericClass<int>
    {
    }
}

如果子類(lèi)也是泛型的,那么繼承的時(shí)候可以不指定具體類(lèi)型,例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    /// <summary>
    /// 使用泛型的時(shí)候必須指定具體類(lèi)型,
    /// 這里的具體類(lèi)型是int
    /// </summary>
    public class CommonClass :GenericClass<int>
    {
    }

    /// <summary>
    /// 子類(lèi)也是泛型的,繼承的時(shí)候可以不指定具體類(lèi)型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CommonClassChild<T>:GenericClass<T>
    {

    }
}

2、類(lèi)實(shí)現泛型接口也是這種情況,例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    /// <summary>
    /// 必須指定具體類(lèi)型
    /// </summary>
    public class Common : IGenericInterface<string>
    {
        public string GetT(string t)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// 可以不知道具體類(lèi)型,但是子類(lèi)也必須是泛型的
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CommonChild<T> : IGenericInterface<T>
    {
        public T GetT(T t)
        {
            throw new NotImplementedException();
        }
    }
}

五、泛型約束

先來(lái)看看下面的一個(gè)例子:

定義一個(gè)People類(lèi),里面有屬性和方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public interface ISports
    {
        void Pingpang();
    }

    public interface IWork
    {
        void Work();
    }


    public class People
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public void Hi()
        {
            Console.WriteLine("Hi");
        }
    }

    public class Chinese : People, ISports, IWork
    {
        public void Tradition()
        {
            Console.WriteLine("仁義禮智信,溫良恭儉讓");
        }
        public void SayHi()
        {
            Console.WriteLine("吃了么?");
        }

        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }

        public void Work()
        {
            throw new NotImplementedException();
        }
    }

    public class Hubei : Chinese
    {
        public Hubei(int version)
        { }

        public string Changjiang { get; set; }
        public void Majiang()
        {
            Console.WriteLine("打麻將啦。。");
        }
    }


    public class Japanese : ISports
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public void Hi()
        {
            Console.WriteLine("Hi");
        }
        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }
    }
}

在Main()方法里面實(shí)例化:

People people = new People()
{
        Id = 123,
        Name = "走自己的路"
};
Chinese chinese = new Chinese()
{
        Id = 234,
        Name = "晴天"
};
Hubei hubei = new Hubei(123)
{
        Id = 345,
        Name = "流年"
};
Japanese japanese = new Japanese()
{
        Id = 7654,
        Name = "werwer"
};

這時(shí)有一個(gè)需求:需要打印出Id和Name屬性的值,將ShowObject()方法修改如下:

但是這樣修改報錯了:object類(lèi)里面沒(méi)有Id和Name屬性,可能會(huì )有人說(shuō),強制類(lèi)型轉換一下就行了?。?/p>

public static void ShowObject(object oParameter)
{
         Console.WriteLine("This is {0},parameter={1},type={2}",
         typeof(CommonMethod), oParameter.GetType().Name, oParameter);

         Console.WriteLine($"{((People)oParameter).Id}_{((People)oParameter).Name}");
}

這樣修改以后,代碼不會(huì )報錯了,這時(shí)我們在Main()方法里面調用:

CommonMethod.ShowObject(people);
 CommonMethod.ShowObject(chinese);
 CommonMethod.ShowObject(hubei);
 CommonMethod.ShowObject(japanese);

結果:

可以看出程序報錯了,因為Japanese沒(méi)有繼承自People,這里類(lèi)型轉換的時(shí)候失敗了。這樣會(huì )造成類(lèi)型不安全的問(wèn)題。那么怎么解決類(lèi)型不安全的問(wèn)題呢?那就是使用泛型約束。

所謂的泛型約束,實(shí)際上就是約束的類(lèi)型T。使T必須遵循一定的規則。比如T必須繼承自某個(gè)類(lèi),或者T必須實(shí)現某個(gè)接口等等。那么怎么給泛型指定約束?其實(shí)也很簡(jiǎn)單,只需要where關(guān)鍵字,加上約束的條件。

泛型約束總共有五種。

1、基類(lèi)約束

上面打印的方法約束T類(lèi)型必須是People類(lèi)型。

/// <summary>
/// 基類(lèi)約束:約束T必須是People類(lèi)型或者是People的子類(lèi)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter) where T : People
{
      Console.WriteLine($"{tParameter.Id}_{tParameter.Name}");
      tParameter.Hi();
}

注意:

基類(lèi)約束時(shí),基類(lèi)不能是密封類(lèi),即不能是sealed類(lèi)。sealed類(lèi)表示該類(lèi)不能被繼承,在這里用作約束就無(wú)任何意義,因為sealed類(lèi)沒(méi)有子類(lèi)。

2、接口約束

/// <summary>
/// 接口約束
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static T Get<T>(T t) where T : ISports
{
      t.Pingpang();
      return t;
}

3、引用類(lèi)型約束 class

引用類(lèi)型約束保證T一定是引用類(lèi)型的。

/// <summary>
/// 引用類(lèi)型約束
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static T Get<T>(T t) where T : class
{
      return t;
}

4、值類(lèi)型約束 struct

值類(lèi)型約束保證T一定是值類(lèi)型的。

/// <summary>
/// 值類(lèi)型類(lèi)型約束
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static T Get<T>(T t) where T : struct
{
      return t;
}

5、無(wú)參數構造函數約束 new()

/// <summary>
/// new()約束
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static T Get<T>(T t) where T : new()
{
     return t;
}

泛型約束也可以同時(shí)約束多個(gè),例如:

public static void Show<T>(T tParameter)
            where T : People, ISports, IWork, new()
{
      Console.WriteLine($"{tParameter.Id}_{tParameter.Name}");
      tParameter.Hi();
      tParameter.Pingpang();
      tParameter.Work();
}

注意:有多個(gè)泛型約束時(shí),new()約束一定是在最后。

六、泛型的協(xié)變和逆變

協(xié)變和逆變是在.NET 4.0的時(shí)候出現的,只能放在接口或者委托的泛型參數前面,out 協(xié)變covariant,用來(lái)修飾返回值;in:逆變contravariant,用來(lái)修飾傳入參數。

先看下面的一個(gè)例子:

定義一個(gè)Animal類(lèi):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class Animal
    {
        public int Id { get; set; }
    }
}

然后在定義一個(gè)Cat類(lèi)繼承自Animal類(lèi):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class Cat :Animal
    {
        public string Name { get; set; }
    }
}

在Main()方法可以這樣調用:

// 直接聲明Animal類(lèi)
Animal animal = new Animal();
// 直接聲明Cat類(lèi)
Cat cat = new Cat();
// 聲明子類(lèi)對象指向父類(lèi)
Animal animal2 = new Cat();
// 聲明Animal類(lèi)的集合
List<Animal> listAnimal = new List<Animal>();
// 聲明Cat類(lèi)的集合
List<Cat> listCat = new List<Cat>();

那么問(wèn)題來(lái)了:下面的一句代碼是不是正確的呢?

 List<Animal> list = new List<Cat>();

可能有人會(huì )認為是正確的:因為一只Cat屬于A(yíng)nimal,那么一群Cat也應該屬于A(yíng)nimal啊。但是實(shí)際上這樣聲明是錯誤的:因為L(cháng)ist<Cat>和List<Animal>之間沒(méi)有父子關(guān)系。

這時(shí)就可以用到協(xié)變和逆變了。

// 協(xié)變
 IEnumerable<Animal> List1 = new List<Animal>();
IEnumerable<Animal> List2 = new List<Cat>();

F12查看定義:

可以看到,在泛型接口的T前面有一個(gè)out關(guān)鍵字修飾,而且T只能是返回值類(lèi)型,不能作為參數類(lèi)型,這就是協(xié)變。使用了協(xié)變以后,左邊聲明的是基類(lèi),右邊可以聲明基類(lèi)或者基類(lèi)的子類(lèi)。

協(xié)變除了可以用在接口上面,也可以用在委托上面:

 Func<Animal> func = new Func<Cat>(() => null);

除了使用.NET框架定義好的以為,我們還可以自定義協(xié)變,例如:

/// <summary>
/// out 協(xié)變 只能是返回結果
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListOut<out T>
{
     T Get();
}

public class CustomerListOut<T> : ICustomerListOut<T>
{
     public T Get()
     {
         return default(T);
     }
}

使用自定義的協(xié)變:

// 使用自定義協(xié)變
 ICustomerListOut<Animal> customerList1 = new CustomerListOut<Animal>();
 ICustomerListOut<Animal> customerList2 = new CustomerListOut<Cat>();

在來(lái)看看逆變。

在泛型接口的T前面有一個(gè)In關(guān)鍵字修飾,而且T只能方法參數,不能作為返回值類(lèi)型,這就是逆變。請看下面的自定義逆變:

/// <summary>
/// 逆變 只能是方法參數
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListIn<in T>
{
     void Show(T t);
}

public class CustomerListIn<T> : ICustomerListIn<T>
{
     public void Show(T t)
     {
     }
}

使用自定義逆變:

// 使用自定義逆變
ICustomerListIn<Cat> customerListCat1 = new CustomerListIn<Cat>();
 ICustomerListIn<Cat> customerListCat2 = new CustomerListIn<Animal>();

協(xié)變和逆變也可以同時(shí)使用,看看下面的例子:

/// <summary>
/// inT 逆變
/// outT 協(xié)變
/// </summary>
/// <typeparam name="inT"></typeparam>
/// <typeparam name="outT"></typeparam>
public interface IMyList<in inT, out outT>
{
     void Show(inT t);
     outT Get();
     outT Do(inT t);
}

public class MyList<T1, T2> : IMyList<T1, T2>
{

     public void Show(T1 t)
     {
          Console.WriteLine(t.GetType().Name);
     }

     public T2 Get()
     {
          Console.WriteLine(typeof(T2).Name);
          return default(T2);
      }

      public T2 Do(T1 t)
      {
           Console.WriteLine(t.GetType().Name);
           Console.WriteLine(typeof(T2).Name);
           return default(T2);
       }
 }

使用:

IMyList<Cat, Animal> myList1 = new MyList<Cat, Animal>();
 IMyList<Cat, Animal> myList2 = new MyList<Cat, Cat>();//協(xié)變
 IMyList<Cat, Animal> myList3 = new MyList<Animal, Animal>();//逆變
IMyList<Cat, Animal> myList4 = new MyList<Animal, Cat>();//逆變+協(xié)變

七、泛型緩存

在前面我們學(xué)習過(guò),類(lèi)中的靜態(tài)類(lèi)型無(wú)論實(shí)例化多少次,在內存中只會(huì )有一個(gè)。靜態(tài)構造函數只會(huì )執行一次。在泛型類(lèi)中,T類(lèi)型不同,每個(gè)不同的T類(lèi)型,都會(huì )產(chǎn)生一個(gè)不同的副本,所以會(huì )產(chǎn)生不同的靜態(tài)屬性、不同的靜態(tài)構造函數,請看下面的例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class GenericCache<T>
    {
        static GenericCache()
        {
            Console.WriteLine("This is GenericCache 靜態(tài)構造函數");
            _TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
        }

        private static string _TypeTime = "";

        public static string GetCache()
        {
            return _TypeTime;
        }
    }
}

然后新建一個(gè)測試類(lèi),用來(lái)測試GenericCache類(lèi)的執行順序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class GenericCacheTest
    {
        public static void Show()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(GenericCache<int>.GetCache());
                Thread.Sleep(10);
                Console.WriteLine(GenericCache<long>.GetCache());
                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);
            }
        }
    }
}

Main()方法里面調用:

GenericCacheTest.Show();

結果:

從上面的截圖中可以看出,泛型會(huì )為不同的類(lèi)型都創(chuàng )建一個(gè)副本,所以靜態(tài)構造函數會(huì )執行5次。 而且每次靜態(tài)屬性的值都是一樣的。利用泛型的這一特性,可以實(shí)現緩存。

注意:只能為不同的類(lèi)型緩存一次。泛型緩存比字典緩存效率高。泛型緩存不能主動(dòng)釋放

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

丰满少妇被猛烈进入毛片| 1717国产精品久久| 色综合色国产热无码一| 国产精品久久无码不卡黑寡妇| 中国女人和老外的毛片| 粗大的内捧猛烈进出|