1. 程式人生 > >C#之泛型

C#之泛型

參數 star 通過 cond 測試結果 form dcl work child

---恢復內容開始---

泛型即一個方法可以傳遞多種不同的類型的時候,就用泛型。泛型是C#2.0語法新特性,也是.net framework框架升級的結果。

 //引入泛型
    public class IntroduceGeneric
    {
        //普通方法
        public void ShowInt(int i)
        {
            Console.WriteLine(i);
        }
        public void ShowString(string s)
        {
            Console.WriteLine(s);
        }
        
public void ShowDateTime(DateTime t) { Console.WriteLine(t); } //泛型方法 public void Show<T>(T t) { Console.WriteLine(t); } }
static void Main(string[] args)
        {
            int i = 2;
            string s = "abc";
            DateTime dateTime 
= DateTime.Now; IntroduceGeneric introduceGeneric = new IntroduceGeneric(); Console.WriteLine("普通方法"); introduceGeneric.ShowInt(i); introduceGeneric.ShowString(s); introduceGeneric.ShowDateTime(dateTime); Console.WriteLine("泛型方法
"); introduceGeneric.Show<int>(i); introduceGeneric.Show<String>(s); introduceGeneric.Show<DateTime>(dateTime); }

從上面兩段代碼可以看出,用一個泛型方法可以代替多種普通的方法。這時候可以有人想到用object類型傳參,下面就試試obejct。

   //泛型方法
        public void Show<T>(T t)
        {
            Console.WriteLine(t);
        }
        //基於object類型傳參
        public void ShowObject(object o)
        {
            Console.WriteLine(o);
        }
   Console.WriteLine("泛型方法");
            introduceGeneric.Show<int>(i);
            introduceGeneric.Show<String>(s);
            introduceGeneric.Show<DateTime>(dateTime);
            Console.WriteLine("用object類型傳參方法");
            introduceGeneric.ShowObject(i);
            introduceGeneric.ShowObject(s);
            introduceGeneric.ShowObject(dateTime);

運行結果

技術分享圖片

從運行結果可以看出 ,泛型方法和object傳參沒有什麽區別。其實很容易理解,因為object 是一切類型的父類。下面我們從性能方面來比較泛型和object傳參方法。

 public class PerformanceTest
    {
        public static IntroduceGeneric introduceGeneric = new IntroduceGeneric();
        public static void CommonMethod()
        {
            Console.WriteLine("執行10000000次普通方法消耗時間");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int i = 10;
            for (var t = 0; t < 10000000; t++)
            {
                introduceGeneric.ShowInt(i);
            }
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
        }
        public static void GenericMethod()
        {
            Console.WriteLine("執行10000000次泛型方法消耗時間");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int i = 10;
            for (var t = 0; t < 10000000; t++)
            {
                introduceGeneric.Show<int>(i);
            }
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
        }
        public static void ObjectMethod()
        {
            Console.WriteLine("執行10000000次object參數方法消耗時間");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int i = 10;
            for (var t = 0; t < 10000000; t++)
            {
                introduceGeneric.ShowObject(i);
            }
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
        }


    }

為了便於查看,將方法裏面的代碼置空,即不輸出上文中的內容。。下面就看比較結果

技術分享圖片

可以看出 泛型方法和普通方法幾乎一樣 甚至性能還由於普通方法 而object參數方法 則消耗的時間大概是泛型方法的兩倍。原因是object在上述過程中進行了大量的裝箱與拆箱操作。

泛型除了應用與泛型方法 還可以是泛型類、泛型接口 、泛型委托。

public class GenericClass<T>
    {
        public T t { get; set; }
        public void  Fun()
        {
            this.t = default(T);
            Console.WriteLine(t?.ToString());
        }
    }


 Console.WriteLine("泛型類");
            GenericClass<int> genericClass = new GenericClass<int>();
            genericClass.Fun();
            GenericClass<string> genericClass2 = new GenericClass<string>();
            genericClass2.Fun();
            GenericClass<DateTime> genericTest3 = new GenericClass<DateTime>();
            genericTest3.Fun();

測試結果:

技術分享圖片

泛型類的繼承

 public class GenericChildClass : GenericClass<int>
    {
    }
    public class GenericChildClass2<T, S> : GenericClass<T>
    {
    }

//註意當子類不是泛型類的時候,父類的泛型一定要指明具體的類型。如果不指明,父類的類型不能確定
//單子類中包含父類中的泛型類型時,父類可以不指明,以為這時唯一一個子類對應唯一一個父類

泛型接口,泛型委托

//泛型接口
    public interface IGeneric<T>
    {
        void IFun(T t);
    }
    //泛型委托
    public delegate void GenericDelegate<T>(T t);

泛型約束

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

       
    }
    //泛型約束
    public class GenericConstraint
    {
        //要求定義一個方法實現打印people的姓名和名稱
        public void CommonPrint(People people)
        {
            Console.WriteLine($"姓名:{people.Name} 年齡:{people.Age}");
        }
        public void GenericPrint<T>(T t) where T : People
        {
            Console.WriteLine($"姓名:{t.Name} 年齡:{t.Age}");
            
        }
        public void ObjectPrint(object t)
        {
            //Console.WriteLine($"姓名:{t.Name} 年齡:{t.Age}");報錯  編譯不能通過
        }
    }
    //泛型約束實現了可以訪問泛型約束了的公開方法和屬性、字段
    //object參數方法則不行  這就是我們常說的類型安全問題

泛型約束的種類

1.基類約束

2.接口約束

3.值類型約束

4.引用類型約束

5.無參構造函數約束

//約束種類
        public void GenericType<T>(T t)
            //where T : new()//基類約束 約束類型必須包含無參構造函數  其他有參構造函數可有可無
            //where T:struct// 值類型約束
            //where T:class//引用類型約束
            //where T:ISport//接口約束
            where T:People,ISport //多重約束,既是People類型(含子類) 並且實現了ISport接口(子類父類都可以)
        {
            
        }

---恢復內容結束---

C#之泛型