C# Delegate 委派 使用方法
記住先
http://rfid-fantasy.blogspot.com/2009/07/c-delegate.html
C# 提供 delegate 修飾子來宣告一個委派方法:
public delegate String getNameDelegate(String n);
委派方法的參數個數、順序、型態乃至於回傳型態都必須跟要被委派的方法一樣 (但變數名稱可以不相同)。下面是我們要委派這個 getNameDelegate 方法呼叫的一個方法:
public static String getName(String name){ return "g1: " + name; }
所以我們把 getName 想成打開電視機,getNameDelegate 當作遙控器,這樣可以多少理解吧?
要呼叫委派方法,有許多方法,隨著 C# 版本的演進已經越來越方便,就從最複雜的開始說起吧。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { public delegate String getNameDelegate(String n); static void Main(string[] args) { getNameDelegate g0 = new getNameDelegate(getName); getNameDelegate g1 = getName; getNameDelegate g2 = delegate(String n) { return "g2: " + n; }; getNameDelegate g3 = n => "g3: " + n; Console.WriteLine(g0("0")); Console.WriteLine(g1("1")); Console.WriteLine(g2("2")); Console.WriteLine(g3("3")); Console.ReadKey(); } public static String getName(String name){ return "g1: " + name; } } }
首先是 getNameDelegate g0 = new getNameDelegate(getName); 這段,這是最早的方法。你就將 getNameDelegate 給實體化,並在其建構元上指定要代為執行的方法 (如 getName) 就可以了。
因為這樣太麻煩,所以後來的 C# 支援這種寫法:getNameDelegate g1 = getName; 是不是更直覺呢?
C# 2.0 中,增加了匿名方法的建立,像我們的 getName 這麼簡單的一行,可以簡化為
getNameDelegate g2 = delegate(String n) { return "g2: " + n; };
這樣,利用 delegate(){ } 來定義匿名方法。
C# 3.0 中,更以 Lambda 運算式取 代匿名方法,一行 getNameDelegate g3 = n => "g3: " + n; 輕鬆打發。 n => "g3: " + n; 就是所謂的 Lambda 運算式。例如 x => x * x 就是「傳入 x,執行 x * x 並回傳」。
最後準備好 g1 等委派物件後,就可以開始執行了。執行的方式有兩種,一種是 g1.Invoke(); 來引發,另一種是更為直覺的 g1(); 直接執行。
這麼看起來委派只是代為執行,並沒有什麼好用的感覺啊。像上面的例子,我大可直接呼叫 getName() 就好,為什麼還要繞一圈以 getNameDelegate 包裝起來再呼叫呢?脫褲子放屁嗎?
getNameDelegate g1 = getName; g1("Scribe"); getName("Scribe");
They're the same!
雖然我現在還搞不懂委派有什麼好的,不過我發現委派他可以一次呼叫代為多個方法,這樣就比較有用多了。例如我按下遙控器的開關,就可以幫我把電視、冷氣、電燈等開關一次打開,不是很方便嗎?所以下面要教你怎麼一次委派多個方法。
using System; namespace ConsoleApplication1 { class Program { public delegate void consoleDelegate(String txt); public delegate void printNameDelegate(String n, consoleDelegate p); static void Main(string[] args) { var g0 = new printNameDelegate(printName); g0 += delegate(String n, consoleDelegate p) { p("Call from anonymous func: " + n); }; g0 += (n, p) => p("Call from Lambda: " + n); g0("scribe", print2Console); Console.ReadKey(); } public static void printName(String name, consoleDelegate p) { p(name); } public static void print2Console(String txt){ Console.WriteLine(txt); } } }
Result:
scribe
Call from anonymous func: scribe
Call from Lambda: scribe
var g0 = new printNameDelegate(printName);
g0 += delegate(String n, consoleDelegate p) { p("Call from anonymous func: " + n); };
g0 += (n, p) => p("Call from Lambda: " + n);
上面三行分別以不同的方式創造出委派物件,跟上面範例的不同點是以 += 串接,讓 g0 一次代理多個方法,最後再一次執行。所以 g0() 的結果有三行。這樣就可以呼叫一個委派物件,同時作數件事情了。
值 得一提的是本範例用了兩個 delegate,其中一個用在 print2Console 上,讓其他方法能夠叫用。printName 第二個參數就是 delegate,其實很像是方法的指標之類的。(因為不可以直接指定第二個變數型別為 print2Console,所以使用委派方式)
我比較喜歡 delegate{} 建立匿名方法跟直接使用 () 來呼叫委派物件,你呢?

0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home