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

程式設計師不帥哥發表於2021-01-11

一、基礎定義

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

  在這個過程中,

  • 事件就是:”老張吃完飯去喝茶“
  • 委託就是:“把前門的苞谷收了”
  • 回撥函式就是:“找老張的老婆去耍”
  • 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

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

 

相關文章