1. 程式人生 > >C# 泛型,泛型約束

C# 泛型,泛型約束

image info dialect pre LEDE read fan 問題 val

泛型主要是為了解決代碼的復用性

在泛型出現之前,如果需要用到不同的參數類型,但是方法體一樣的時候,需要定義多個不同類型參數的方法,這樣有太多的重復代碼如下

       public static void ShowInt(int iParameter)
        {
            Console.WriteLine("類名稱:"+typeof(TestFunctionClass).FullName+",參數類型:"+ iParameter.GetType().ToString() + ",參數Value:"+iParameter);
        }

        public
static void ShowString(string sParameter) { Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + sParameter.GetType().ToString() + ",參數Value:" + sParameter); } public static void ShowDate(DateTime dParameter) { Console.WriteLine(
"類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + dParameter.GetType().ToString() + ",參數Value:" + dParameter); }

在Main方法中進行調用

 Console.WriteLine("最開始展示不同類型參數的信息的時候,需要定義多個不同類型的方法,而方法內容是幾乎一樣的");
  TestFunctionClass.ShowInt(1);
  TestFunctionClass.ShowString("aaa");
  TestFunctionClass.ShowDate(DateTime.Now);
  Console.ReadLine();

輸出結果

技術分享圖片

後來發現使用裏氏替換原則,任何使用父類的地方可以使用子類來進行替換,於是有了下面這種寫法(object是任何子類的父類)

 public static void ShowObject(object oParameter)
 {
     Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + oParameter.GetType().ToString() + ",參數Value:" + oParameter);
 }

在主方法中可以直接傳遞

 Console.WriteLine("後來發現通過裏氏替換原則,任何父類出現的地方可以用子類來進行替換,可以節省大部分代碼");
 TestFunctionClass.ShowObject(2);
 TestFunctionClass.ShowObject("bbb");
 TestFunctionClass.ShowObject(DateTime.Now);
 Console.WriteLine("但是這樣出現一個問題,出現類類型之間的轉換,發生了裝箱操作,這樣使性能得到了非常大的損耗,(值類型轉換為引用類型)");

輸出結果

技術分享圖片

這個時候出現了泛型,泛型是在定義的時候,不直接聲明類型,直到調用的時候再去指定,延時聲明的作用,避免了裝箱操作,減少了性能損耗

        public static void ShowFanXing<T>(T tParameter)
        {
            Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + tParameter.GetType().ToString() + ",參數Value:" + tParameter);
        }

在主方法中調用

     TestFunctionClass.ShowFanXing<int>(3);
        TestFunctionClass.ShowFanXing<string>("ccc");
        TestFunctionClass.ShowFanXing<DateTime>(DateTime.Now);
        Console.WriteLine("使用泛型的時候性能和使用普通方法類似,遠大於通過object(裏氏替換原則)的性能(前提:如果發生了裝箱操作的時候");

輸出結果

技術分享圖片

這個時候,泛型的定義知道了,但是咱們發現好像泛型沒有什麽意義,在方法內只能使用的還是基類的一些屬性和方法

這個時候需要引入一個東西,泛型約束,通過泛型約束,咱們可以在泛型方法(泛型類)中使用約束的屬性和方法

先聲明一些基礎類

    public class Pepple
    {
        public int Age { get; set; }

        public string Name { get; set; }

        public string SayHi()
        {
            return "Hi,My Name is" + Name + ",My Age Is " + Age;
        }
    }

    public class Chinese : Pepple, ISiChuan
    {
        public string Dialect { get; set; }
        public string Food()
        {
            return "火鍋";
        }
    }

    public class Japanese : Pepple, IGuangDao
    {
        public string ViewSakura()
        {
            return "美しい桜";
        }
    }

    public interface ISiChuan
    {
        string Dialect { get; set; }

        string Food();
    }

    public interface IGuangDao
    {
        string ViewSakura();
    }

泛型方法

 public static void ShowPeople<T>(T tParameter) where T : Pepple
 {
     Console.WriteLine("名字:" + tParameter.Name + ",年齡:" + tParameter.Age);
     Console.WriteLine("說話:" + tParameter.SayHi());
 }

在主方法中可以進行調用

   Pepple people = new Pepple()
     {
         Age = 1,
         Name = "People Name"
     };
     //裏氏替換原則
     Pepple chinese = new Chinese()
     {
          Age = 1,
          Name = "張三"
      };

      TestFunctionClass.ShowPeople<Pepple>(people);
      TestFunctionClass.ShowPeople<Pepple>(chinese);
      Console.WriteLine("這個時候還有一個問題,雖然用了泛型約束,可以使用約束類的屬性和方法,但是,子類的一些特性還是不能訪問,這個時候出現了接口約束");
      Console.ReadLine();

輸出結果

技術分享圖片

泛型接口約束

public static void ShowPeopleDetail<T>(T tParameter) where T : Pepple, ISiChuan
{
     Console.WriteLine("名字:" + tParameter.Name + ",年齡:" + tParameter.Age);
     Console.WriteLine("說話:" + tParameter.SayHi());
     Console.WriteLine("喜歡吃:" + tParameter.Food());
}

執行結果

技術分享圖片

結束

C# 泛型,泛型約束