1. 程式人生 > >C#高階程式設計三十一天----泛型總結

C#高階程式設計三十一天----泛型總結

C#泛型總結

C#中的所謂的泛型程式設計和C++中相應的模版類似.

泛型方法

C#中的泛型方法是指使用了型別引數的方法成員,案例:

   static void Main(string[] args)

        {

            int a=1;

            int b=2;

            Swap<int>(ref a,ref b);

            //Swqp(ref a,ref b);效果和上面一句相同

            Console.WriteLine("a = {0},b = {1} ",a,b);

        }

        public static void Swap<T>(ref T x,ref T y)

        {

            T temp=x;

            x=y;

            y=temp;

        }

在使用泛型方法的時候需要注意幾點:

1.泛型方法可以對其引數型別進行型別限制其中包括:主要限制,次要限制,函式限制

2.C#中是不允許對類的建構函式,屬性,事件,索引函式和操作符等特殊函式定義為泛型方法的.

3.泛型方法也可以被定義為虛方法,過載方法,抽象方法或者密封方法等,泛型方法也可以實現override過載,也能利用其實現多型麼還有一點就是在派生類中過載基類中的泛型方法時,會自動繼承基類中的泛型方法的所有型別限制,沒有必要再去重新宣告一遍

,當然重新宣告也是錯誤的.

4.泛型方法是可以通過委託機制來呼叫的,其實現機制有兩種,分別是:”普通委託”和”泛型委託”

案例:

 public static void Swap<T>(ref T x,ref T y)

        {

            T temp=x;

            x=y;

            y=temp;

        }

        public static void Clear<T>(ref T x, ref T y)

        {

            x = default(T);

            y = default(T);

        }

補充:在泛型類和方法中,在預先未知以下情況時,如何將預設值分配給引數化型別T:

1.T是引用型別還是值型別

2.如果T是值型別,則它是數值還是結構

3.如果T是引用型別,t=null有效,T為數值型別,t=0才有效,若為結構,則要符合結構中的每個型別.

所以在我們不確定的情況下,使用default關鍵字,系統會自動的為他分配預設值.

public T Delete(T t)

{

T temp=default(T);

//action

return temp;

}

因為事先不知道T是何種型別,可能是int型可能是string型別,或者是結構.

在這種情況下,要返回函式結果時,使用default就可以返回一個預設值了,因為都是系統為我們做這些.

普通委託:

public delegate void fun(ref int x,ref int y);

int a=1;

int b=2;

fun fun1;

fun1=Swap<int>;

fun1(ref a, ref b);

泛型委託:

public delegate void fun<T>(ref T x,ref T y);

fun<int> fun2;

fun2=Swap<int>;

fun2(ref a, ref b);

泛型類和泛型介面

案例:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace ConsoleApplication11

{

    class Program

    {

        static void Main(string[] args)

        {

        }

    }

    public class LinkNode<T>

    {

        protected T data;

        protected LinkNode<T> next;

        public T Data

        {

            get { return data; }

            set { data = value; }

        }

        public LinkNode<T> Next

        {

            get { return next; }

            set { next = value; }

        }

        public LinkNode()

        {

            data = default(T);

        }

        public LinkNode(T t)

        {

            data = t;

        }

        public static LinkNode<T> operator >>(LinkNode<T> node, int n)

        {

            LinkNode<T> node1 = new LinkNode<T>();

            node1 = node;

            for (int i = 0; i < n; i++)

            {

                node1 = node.next;

            }

            return node1;

        }

        public static bool operator ==(LinkNode<T> t1, LinkNode<T> t2)

        {

            //return (t1.Data ==t2.Data);

            //錯誤不能直接將比較符運用到未知型別的T型別中

            //但是可以直接利用object類中的比較方法如Equals();

            return (t1.Data.Equals(t2.Data));

        }

    }

}

分析:

1.泛型類的建構函式名稱是與類名同名的,並不包括型別引數

2.不能隨意的在泛型類中將比較運算子運用於引數型別的物件中,這樣一定會報錯,但是如果是運用object類中的相關方法是可行的的.

3.在一個泛型類中可以使用多個泛型引數

4.泛型類本身不能擁有任何東西,只有泛型類的構造型別和其具體例項才能擁有成員方法或資料成員.而在C#中泛型類中的靜態成員則是屬於該泛型類的構造型別

5.無論是在寫泛型類,泛型介面或是泛型方法時都可以加上型別限制,C#支援在泛型定義過程中通過where關鍵字來對型別引數進行限制,限制方式主要包括:主要限制(可以限制為struct值型別或者class引用型別),次要限制(限制該型別引數必須從指定的基類或介面繼承而來),建構函式限制(要求型別引數的目標型別必須提供一個無參的建構函式),這裡的型別限制在C#的程式設計中提供了極大的方便,這是C++中的模板不能匹敵的,但同時犧牲了一些靈活性.

6.由泛型型別所引發的泛型類的繼承問題,在泛型類之間的繼承中有一天基本的原則就是:開放型別不能作為封閉型別的基類.    也就是說,在普通類繼承泛型類時,非泛型的普通類是不能直接繼承自泛型類的,但能繼承自泛型類的封閉建構函式.就是在繼承的過程中類的”開放性”不能變小,但能變大或者不變.