1. 程式人生 > >C#中委託與事件的學習小結(一)

C#中委託與事件的學習小結(一)

最近又學習了一些C#的小知識點,在此釋出部落格記錄一下。

一、委託

C#中的委託的關鍵字是delegate,我們可以使用委託型別來將已有的方法例項化出來,也可以將我們自己定義的方法作為引數來傳遞。

例如: private delegate string GetAString();//我們定義一個委託型別,這個委託的名字是GetAString

             static void Main(string[] args)         {     

            int x = 40;//定義了一個變數為x,為其賦值為40

            GetAString a = new GetAString(x.ToString);//傳遞一個方法為引數,相當於a指向了x中的ToString方法。

            //GetAString a = x.ToString;//第二種賦值方法,直接將方法賦值給委託變數。

            string s = a();//通過委託的例項去呼叫x中的ToString方法。

            Console.WriteLine(s);

            Console.ReadKey();

        }

上面這個例子中,存在兩種對委託型別變數a的賦值,第一種方法是直接改變a的指向,將ToString方法作為引數,傳遞給a,而第二種方法,則是直接將x中的方法賦值給a。這是已有方法ToString利用委託型別例項化出來的例子。下面分享一個自己定義方法作為引數進行委託傳遞的例子。

例:

        private delegate void PrintString();//首先定義一個委託型別

        static void PrintStr(PrintString print)//委託型別可以作為引數傳遞。         {             print();         }

      //定義的變數需要初始化才可以使用,所以新建立兩個方法,用來初始化method;

        static void Method1()         {             Console.WriteLine("method1");         }         static void Method2()         {             Console.WriteLine("method2");         }

        static void Main(string[] args) {

            PrintString method=Method1;//使用Method1方法來初始化method委託變數             PrintStr(method);//利用定義好的函式PrintStr來輸出method方法             method = Method2;//委託型別重新複製,呼叫引數改變,輸出結果也改變             PrintStr(method);             Console.ReadKey();

        }

大家可以注意到,我輸出了2次method委託變數,但是2次的結果是不同的,因為我們利用賦值的方式,在輸出Method1方法後將委託變數的值改變為Method2方法。而這個方法引數,正是我們一開始定義的PrintString委託型別的print方法。

二、Action委託和Func委託

下面說一下C#語言中為我們定義好的兩個委託型別:

1、Action委託

這個委託最大的特點是它只能指定沒有返回值的方法,也就是void型別的方法,而他傳遞的方法中可以包含0個或多個引數。也就是說,既沒有引數也沒有返回值的方法也可以通過Action委託進行傳遞。

例:  static void PrintDoubleInt(int i1, int i2)//我們先定義一個方法,注意它沒有返回值         {             Console.WriteLine(i1+i2);         }

        static void Main(string[] args)         {

          Action<int , int> a=PrintDoubleInt;//我們將方法中的2個引數利用泛型<>來傳遞。

          a(23,33);//然後我們隨意在委託變數a中傳遞兩個引數。

          Console.ReadKey();

          }

這裡要注意,Action後面泛型中的型別,一定要與宣告此方法中的引數一一對應。然後輸出結果為兩個int引數的和。

2、Func委託

這個委託跟Action委託正好對應,他是必須要有返回值的委託型別。引數方面與Action委託要求基本一致,可以有0個或多個引數,但是方法的返回值型別不能為空。

例: static int Test3(int i, int j)         {             return i + j;         }        

        static void Main(string[] args)         {             Func<int, int, int> a = Test3;//func後面必須指定一個返回值型別,引數型別可以有0-16個,                                           //先寫引數型別,最後一個是返回值型別。             int res = a(1, 5);             Console.WriteLine(res);             Console.ReadKey();         }

通過例子我們可以發現Func後面可以跟很多型別,最後一個是返回值型別,前面的型別是引數型別,引數型別必須跟指向的方法的引數型別按照順序對應。

三、多播委託

下面跟大家說一下什麼是多播委託。多播委託就是一個將各個委託集合到一起,做成一個Delegate[],然後我們同樣可以通過foreach的方法,對其內部的委託進行查詢。那麼我們如何將各種方法集合到一起呢?下面寫個小例子,大家就明白了。

例://常規建立兩個測試方法:

        static void Test1()         {             Console.WriteLine("test1");         }

        static void Test2()         {             Console.WriteLine("test2");         }

        static void Main(string[] args)         {             Action a = Test1;//將Test1賦值給委託a;

            a += Test2;//通過+=符號,為委託變數增加Test2方法;

            a();

            Console.ReadKey();

           }

我們可以通過+=和-=這兩個符號,對委託型別a中的方法集合進行增減,但是要注意,如果這個委託集合中有任何一個方法發生異常的話,整個集合的迭代都會停止。