C#掃盲篇(三):Action和Func委托--實話實說


一、基礎定義

  老王想找老張的老婆出去耍,但是一看,老張還在廚房煮飯。於是老王就對老張隔壁的淑芬說:“等下老張吃完飯出去喝茶,你就把前門曬的苞谷收了,老張從左門出,你就收右邊的苞谷,我就知道從雞舍進來。老張從右門出,你就收左牆的苞谷,我就從側屋FQ進來”。

  在這個過程中,

  • 事件就是:”老張吃完飯去喝茶“
  • 委托就是:“把前門的苞谷收了”
  • 回調函數就是:“找老張的老婆去耍”
  • sender就是:老張
  • 事件句柄就是: 淑芬
  • EventArgs就是事件參數 : 收左邊的苞谷還是右邊的苞谷

1.聲明格式:      

  ——用關鍵字“delegate”修飾委托      

  ——委托的返回類型和參數要和被委托的方法保持一致例如:

public class TestClass { public delegate int delegateAction(); public event delegateAction OnActionEvent; public delegateAction daNew; }

2.委托和方法關聯

在聲明了委托和定義好方法之后,我們需要將委托和方法進行關聯,這樣委托才能知道自己要調用的是哪個方法。

//委托和方法關聯
MyDelegate my = new MyDelegate(MyClass.Method1);

3. 委托調用方法

將委托和方法進行關聯之后,我們就可以直接操作委托實例來進行方法的調用,調用方式和直接調用方法差不多。

 //實例化委托的實例方法
 MyClass c = new MyClass(); My my2 = new My(c.Methods);
 my("Hello"); my2("Hello");

4. 效果

  有了上面的使用之后,我們會發現委托基本都是根據具體方法來聲明的,如果不同的方法有3個,4個或者更多的參數,顯然,我們需要分別聲明不同參數個數的委托,不經意間多了一道“聲明委托”的門檻。於是,在.Net Framework3.5版本之后發布了.Net自帶的內置委托Action和Func。我們不用再做“聲明委托”的工作,直接可以使用。

5.Action委托

  Action委托提供無參數、有參數方法,但不提供返回類型,具有Action、Action、Action<t1,t2>、Action<t1,t2,t3>……Action<t1,……t16>多達16個參數的形式,其中傳入參數均采用泛型T,涵蓋了幾乎所有可能存在的無返回值的委托類型。<t1,t2><t1,t2,t3><t1,……t16>
6.Func委托

  Func委托提供無參數、有參數方法,同時提供返回類型,具有Func、Func<t,tresult>……Func<t1,t2,t3……,tresult>17種類型重載,T1……T16為參數,Tresult為返回類型。

前面我們說,Action委托和Func委托不用再聲明,便可直接使用,除了這一點,它們還支持匿名函數、lamda表達式形式。
7.Action委托與Func委托區別

  看出Func與Action是類似的,唯一的區別就是,Func必須指定返回值的類型,使用方式與委托咱們自己使用委托變量是一樣的,直接使用相應參數的Func或者Action聲明變量,=或者+=掛載函數(方法即可)

這兩個其實說白了就是系統定義好的Delegate,他有很多重載的方法,便於各種應用情況下的調用。他在系統的System命名空間下,因此全局可見。

 二、匿名函數

如果你沒有暈的話,再來看一下匿名委托,其實這也是一種偷懶的小伎倆而已
看代碼說話:

//F = new Func<string>(HelloWorld1);

其實也可以簡寫成這樣:

F = HelloWorld1;          

//F2 = new Func<DateTime, string>(HelloWorld2);

其實也可以簡寫成這樣

F2 = HelloWorld2;

方法直接賦值給委托,這二個類型不同吧???

沒錯,你會發現編譯一樣能通過,系統在編譯時在背后自動幫我們加上了類似 “= new Func<...>”的東東,所以我們能偷懶一下下,這個就是匿名委托。

如果你細心的話,會發現我們在定義Button的Click處理事件時,通常是這樣的:

this.button1.Click += new EventHandler(button1_Click);

但有時候我們也可以寫成這樣:

this.button1.Click += button1_Click;

這其實就是匿名委托的應用. 

三、lamda表達式

//使用lambda 表達式
     NoParameter noParameterNew1 = new NoParameter( () => Console.WriteLine("我是:無參無返回值方法") ); Parameter parameterNew1 = new Parameter( (Para) => Para );

 

四、Action委托實例

Action委托和Func委托的唯一區別就是沒有返回類型,其他用法都一樣,當不需要返回類型的時候,直接用Action委托。class Program

 { static void Main(string[] args) { string mid = ",mid"; Action<string> anonDel = delegate (string param) { param += mid; param += " and this."; Console.WriteLine(param); }; anonDel += delegate (string t) { Console.WriteLine(t + System.Guid.NewGuid().ToString()); }; anonDel("www.webczw.com"); Console.ReadKey(); } }
  多學兩招:委托的使用場景示例
  (1)服務器對象可以提供一個方法,客戶端對象調用該方法為特定的事件注冊回調方法。當事件發生時,服務器就會調用該回調函數。通常客戶端對象實例化引用回調函數的委托,並將該委托對象作為參數傳遞。
  (2)當一個窗體中的數據變化時,與其關聯的另外一個窗體中相應數據需要實時改變,可以使用委托對象調用第二個窗體中的相關方法實現。
五、總結

  為了實現方法的參數化,提出了委托的概念,委托是一種引用方法的類型,即委托是方法的引用,一旦為委托分配了方法,委托將與該方法具有完全相同的行為。大家在看的同時一定也要動手實踐,這樣才能把知識變成自己的體系。希望能給一些朋友捋捋思緒,形成自己的知識體系。

 


往期精彩:

 

  首發自:【程序員不帥哥 】公眾號

  原文鏈接:https://mp.weixin.qq.com/s/LCPLjBmmbJwXBDWdi3SU1g

  掃碼關注,更多精彩內容及時獲取,一起提高,一起加油

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM