程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#3.0學習筆記(10)泛型

C#3.0學習筆記(10)泛型

編輯:C#入門知識

 

1, 什麼是泛型?

       在理解泛型的定義之前,我們要明白非泛型的概念,非泛型就是大部分情況下是聲明一個類,然後封裝需要的行為,最後創建這些類的實例。

       泛型是一種更准確地使用有一種以上的類型的代碼的方式。泛型允許我們聲明類型參數化的代碼,我們可以用不同的類型進行實例化。總結為一句話就是,泛型類型是類型的模板。

       請仔細理解下面兩張圖,或許能更好地理解泛型的原理。

      

\

 

\

 

2, 泛型類?

       創建和使用常規的,非泛型的類的過程有兩個步驟:聲明類和創建類的實例。

       泛型的類不是實際的類,而是類的模板,所以我們必須先從它們構建實際的類類型, 然後個構建後的類類型的實例。

       下圖演示了泛型類的創建過程:

  \

 

3, 聲明泛型類?

       聲明一個泛型類和聲明普通類差不多,主要有如下區別:

  1>    在類名之後放置一組尖括號。

  2>    在尖括號中用逗號分隔的占位符字符串來表示希望提供的類型。這叫類型參數(Type Parameter)

  3>    在泛型類聲明的主體中使用類型參數來表示應該被替代的類型。

  如下代碼所示聲明了一個SomeClass的泛型類:

 

www.2cto.com

 

 

 class SomeClass<T1, T2> //聲明泛型類SomeClass,尖括號中是類型參數。

 

     {

 

        public T1 SomeVar = new T1(); //通常在這些位置使用類型。

 

     }

 

 

     注:泛型和非泛型區分的最主要的標志是:泛型類有尖括號。

 

 

 

4, 創建構造類型?

 

       我們不能直接從泛型類型創建實例對象。首先,我們需要告訴編譯器使用哪些真實類型來替代占位符(類型參數)。編譯器獲取這些真實類型並從它創建一個真實類型對象。

 

       創建構造類型例如:

 

SomeClass<short,int> //尖括號中為類型實參

 

 

5, 創建泛型類的變量和實例?

 

       創建泛型類實例一般有兩種方法:

 

       方法一:和普通非泛型類的對象創建方法相似

 

SomeClass<short, int> mySc1 = new SomeClass<short, int>(); //第一種方法創建泛型類實例。

      方法二:使用Var關鍵字隱式創建:

 

 

 

var mySc2 = new SomeClass<short, int>(); //第二種方法,使用Var關鍵字創建。

 

 

      例如:

 

         class Program

 

    {

 

        static voidMain(string[] args)

 

        {

 

            var stackInt = new MyStack<int>(); //創建泛型類對象(或稱實例),創建構造類型和創建實例可以一步完成。

 

            var stackString=new MyStack<String>();

 

 

 

            stackInt.Push(3); //調用方法

 

            stackInt.Push(5);

 

            stackInt.Push(7);

 

            stackInt.Print();

 

 

 

            stackString.Push("Generics are great!");

 

            stackString.Push("Hi there");

 

            stackString.Print();

 

 

 

            Console.ReadKey();

 

        }

 

    }

 

    class MyStack<T> //聲明泛型類

 

    {

 

        T[] StackArray; //聲明數組

 

        int StackPointer = 0; //聲明並初始化整形變量。

 

        public void Push(T x) //定義無返回值方法

 

        {

 

            if (!IsStackFull)

 

            {

 

                StackArray[StackPointer++] = x; //為數組StackArray賦值。

 

            }

 

        }

 

        public T Pop() //定義有返回值方法

 

        {

 

            return (!IsStackEmpty) //條件運算符,可以用if...else...語句等價表示。

 

                ? StackArray[--StackPointer]

 

                : StackArray[0];

 

        }

 

        public MyStack() //構造函數初始化數組StackArray,為數組分配內存引用。

 

        {

 

            StackArray=new T[MaxStack];

 

        }

 

        public void Print() //構造函數

 

        {

 

            for (int i = StackPointer - 1; i >= 0; i--)

 

            {

 

                Console.WriteLine("Value:{0}",StackArray[i]);

 

            }

 

        }

 

 

 

        const int MaxStack = 10; //聲明並初始化常量MaxStack

 

        bool IsStackFull //聲明屬性

 

        {

 

            get { return StackPointer >= MaxStack; }

 

        }

 

        bool IsStackEmpty //聲明屬性

 

        {

 

            get { return StackPointer <= 0; }

 

        }

 

    }

 

 

 

     程序輸出結果為:

\

       附:泛型棧和非泛型棧之間的區別總結如下圖表:

 

非泛型

泛型

源代碼大小

更大:我們需要為每種類型進行一個新的實現。

更小:不管構造類型的數量多少,我們只需要一個實現。

可執行大小

無論每一個版本的棧是否會被使用,都會在編譯的版本中出現。

可執行文件中只會出現有構造類型的類型。

寫的難易度

易於書寫

比較難寫

維護的難易度

更容易出問題,因為所有修改需要應用到每一個可用的類型上。

易於維護,因為只需要修改一個地方。

 

 

 

 

 

 

 

 

 

 

6, 泛型結構?

       例如:

	struct PieceOfData<T> //聲明泛型結構

 

    {

 

        public PieceOfData(T value) //構造函數,初始化字段_Data。

 

        {

 

            _Data = value;

 

        }

 

        private T _Data;//聲明私有字段(只能在類的內部訪問)。

 

        public T Data //聲明屬性

 

        {

 

            get { return _Data; }

 

            set { _Data = value; }

 

        }

 

    }

 

 

 

    class Program

 

    {

 

        static voidMain()

 

        {

 

            var intData=new PieceOfData<int>(10);//創建構造類型實例

 

            var stringData=new PieceOfData<string>("Hi there!");

 

 

 

            Console.WriteLine("intData={0}",intData.Data);//訪問屬性

 

            Console.WriteLine("stringData={0}",stringData.Data);

 

            Console.ReadKey();

 

        }

 

    }

	

 

      程序輸出結果為:

    \

 

7, 泛型接口?

       泛型接口的聲明和非泛型接口的聲明差不多,但是需要在接口名稱之後的尖括號中有類型參數。

       例如:

 

 

    interface IMyIfc<T> //聲明泛型接口,尖括號中為類型參數。

 

    {

 

        T ReturnIt(T inValue); //聲明返回值類型為T的方法

 

    }

 

 

 

    class Simple<S> : IMyIfc<S> //聲明泛型類,實現了泛型接口。

 

    {

 

        public S ReturnIt(S inValue) //實現接口成員方法。

 

        {

 

            return inValue;

 

        }

 

    }

 

 

 

    class Program

 

    {

 

        static voidMain(string[] args)

 

        {

 

            var trivInt = new Simple<int>(); //創建構造類型實例。尖括號中為類型實參。

 

            var trivString = new Simple<string>();

 

 

 

            Console.WriteLine("{0}",trivInt.ReturnIt(50)); //調用類對象實現的方法。

 

            Console.WriteLine("{0}",trivString.ReturnIt("Hi there!"));

 

 

 

            Console.ReadKey();

 

        }

 

    }

 

 

 

      程序輸出結果為:

 

    \

 

8, 泛型委托?

  1>    要聲明泛型委托,在委托名稱之後,委托參數列表之前的尖括號中放類型參數列表。

  2>    注意,在這裡泛型委托有兩個參數列表:委托形參列表和類型參數列表。

  例如:

 

 

delegate void MyDelegate<T>(T value); //聲明泛型委托

 

  

 

    class Simple

 

    {

 

        public static void PrintString(string s) //方法匹配委托,

 

        {

 

            Console.WriteLine(s);

 

        }

 

 

 

        public static void PrintUpperString(string s)

 

        {

 

            Console.WriteLine("{0}", s.ToUpper());//調用string的ToUpper方法實現將字符串轉換為大寫。

 

        }

 

    }

 

 

 

    class Program

 

    {

 

        static voidMain(string[] args)

 

        {

 

            var MyDel = new MyDelegate<string>(Simple.PrintString); //創建委托的實例

 

            MyDel += Simple.PrintUpperString; //為委托添加方法。

 

            if (null != MyDel) //判斷委托是否為空。

 

            {

 

                MyDel("VinceInfo");//調用委托。

 

            }

 

            else

 

            {

 

                Console.WriteLine("Delegate is empty!");

 

            }

 

            Console.ReadKey();

 

        }

 

    }

 

 

 

     程序輸出結果如下:

 

  \

 

9, 泛型方法?

       泛型方法和泛型委托相似,有兩個參數列表:

  1>    封閉在圓括號內的方法參數列表。

  2>    封閉在尖括號內的類型參數列表。

\

   例如:

 

 

class Simple //非泛型類

 

    {

 

        static public void ReverseAndPrint<T>(T[] arr) //聲明泛型方法

 

        {

 

            Array.Reverse(arr);

 

            foreach (T item in arr) //遍歷數組。使用類型參數T。

 

            {

 

                Console.Write("{0}",item.ToString());

 

                Console.Write("");

 

            }

 

            Console.WriteLine(); //換行

 

        }

 

    }

 

 

 

    class Program

 

    {

 

        static voidMain(string[] args)

 

        {

 

            //創建三種類型的數組。

 

            var intArray = new int[] { 3,5,7,9,11};

 

            var stringArray = new string[] { "first","second","third"};

 

            var doubleArray = new double[] { 3.567,7.891,2.345};

 

 

 

            Simple.ReverseAndPrint<int>(intArray); //調用泛型方法,顯示調用

 

            Simple.ReverseAndPrint(intArray); //使用推斷類型隱式調用。

 

 

 

            Simple.ReverseAndPrint<string>(stringArray);

 

            Simple.ReverseAndPrint(stringArray);

 

 

 

            Simple.ReverseAndPrint<double>(doubleArray);

 

            Simple.ReverseAndPrint(doubleArray);

 

 

 

            Console.ReadKey();

 

 

 

        }

 

    }

 

  程序輸出結果為:

   \

 

10,擴展方法和泛型類?

       擴展方法可以和泛型類結合使用,它允許我們將類中的靜態方法關聯到不同的泛型類上,還允許我們像調用類構造實例的實例方法一樣來調用方法。

       例如:

 

 

       static class ExtendHolder

 

    {

 

        public static void Print<T>(this Holder<T> h) //聲明擴展方法並關聯到泛型類Holder<T>上。

 

        {

 

            T[] vals = h.GetValues(); //調用泛型類的方法。

 

            Console.WriteLine("{0},\t{1},\t{2}",vals[0],vals[1],vals[2]); //"\t"轉義符

 

        }

 

    }

 

 

 

    class Holder<T> //聲明泛型類

 

    {

 

        T[] vals=new T[3];//聲明並初始化數組。

 

        public Holder(T v0, T v1, T v2) //構造函數,為數組賦值。

 

        {

 

            vals[0] = v0;

 

            vals[1] = v1;

 

            vals[2] = v2;

 

        }

 

        public T[] GetValues() //聲明方法,返回數組類型。

 

        {

 

            return vals;

 

        }

 

    }

 

 

 

    class Program

 

    {

 

        static voidMain(string[] args)

 

        {

 

            var intHolder = new Holder<int>(3,5,7); //創建泛型類實例

 

            var stringHolder = new Holder<string>("a1","b2","c3");

 

 

 

            intHolder.Print(); //調用方法

 

            stringHolder.Print();

 

 

 

            Console.ReadKey();

 

        }

 

    }

 

 

 

     程序輸出結果為:

 

    \

      關於泛型先寫到這裡,歡迎大家指正,謝謝

 

作者 永遠的麥子

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved