首頁  >  文章  >  後端開發  >  C#中委託與匿名委託的具體介紹

C#中委託與匿名委託的具體介紹

黄舟
黄舟原創
2017-09-02 14:53:541557瀏覽

這篇文章主要為大家詳細介紹了C#委託與匿名委託的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下

#本來是想寫一篇《委託與lambda表達式的前世今生》,但僅委託部分已經寫了很多內容,於是就此分開關於Lambda表達是的內容後續再寫吧。

不知道Lambda表達式是誰發明的,只記得第一次接觸Lambda表達式是在使用VS2008的時候,那就先認為是微軟發明的吧。

Lambda表達式從我接觸開始到現在變得越來越流行,Java8中開始支援、kotlin更是對C#,F#做了廣泛的抄襲(C#曾幾何時不也如此對待過Java嘛) 。其實這都充分說明了,Lambda表達式的重要性。要搞清楚Lambda首先需要搞清楚委託。

委託:

假設現在我們要發展一個處理兩個整數的程式(假設先處理相加運算)


#
public class Worker
    {
      /// <summary>
      /// 处理两个数
      /// </summary>
      /// <param name="a"></param>
      /// <param name="b"></param>
      /// <returns></returns>
      public int HandleTwoNumber(int a,int b)
      {
        return a + b;
      }
    }
static void Main(string[] args)
    {
      int a = int.Parse(Console.ReadLine());
      int b = int.Parse(Console.ReadLine());

      Worker worker = new Worker();
      int result = worker.HandleTwoNumber(a, b);
      Console.WriteLine(String.Format("Result:{0}", result));

      string p = Console.ReadLine();
}

如果一段時間後,我們需要它變更為減操作:


public class Worker
    {
      public int HandleTwoNumber(int a,int b)
      {
        return a - b;
      }
    }

雖然有a+b變成a-b的變化很微小,但後續這裡可能面臨多次變化(由減變為除.........)。有變化就應封裝變化,此處我們可以將a與b的操作行為抽象化出來,用什麼抽象呢?委託


public class Worker
    {
      public delegate int TwoNumberHandleMethodDelegate(int x, int y);
      public int HandleTwoNumber(int a,int b)
      {
        return a + b;
      }
    }

public delegate int TwoNumberHandleMethodDelegate(int x, int y);此處用delegate標註,顯示這是一個委託定義。如果去掉 delegate 再來觀察這個定義,你會發現這就是一個沒有方法體的抽象方法。所以委託的意義即:與該抽象方法簽名形式相同的方法的類型。委託就是一種你定義的新資料類型,它與int、class是一樣的都是資料型別。 int表示整數,只要是整數都可以賦值給 int型變數;TwoNumberHandleMethodDelegate則表示,接收兩個int型參數並傳回int型結果的這類方法,因此滿足上述要求的方法都可賦值給TwoNumberHandleMethodDelegate類型的變數。

如此一來Worker程式碼可修改為:


public class Worker
    {
      public delegate int TwoNumberHandleMethodDelegate(int x, int y);
      public int HandleTwoNumber(int a, int b, TwoNumberHandleMethodDelegate handle)
      {
        return handle(a, b);
      }
    }

如此a、b的運算被封裝起來,所有的變更均交由調用者來處理。此處的意義:HandleTwoNumber處理a、b兩個整數,具體如何處理由 handle 實作。此時你可能會問,那如何來呼叫該方法呢?呼叫如下:


private static int Add(int a, int b)
    {
      return a + b;
    }

    private static int Sub(int a, int b)
    {
      return a - b;
    }

    static void Main(string[] args)
    {
      int a = int.Parse(Console.ReadLine());
      int b = int.Parse(Console.ReadLine());
      Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add);
      Worker worker = new Worker();
      int result = worker.HandleTwoNumber(10, 10,method);
       //int result = worker.HandleTwoNumber(10, 10, Sub);//简化版
      Console.WriteLine(String.Format("Result:{0}", result));
 }

根據上面的程式可知,Main程式碼區塊為worker的呼叫者,作為呼叫者而言應該最清楚自己想要讓woker做的工作。因此作為被呼叫者的worker而言,它只需要接收呼叫者Main給的a\b參數及執行Main定制的演算法method,然後依照演算法執行並傳回結果即可。上面程式碼雖然簡單,但其中的意義深遠,隨著程式設計時間的增加相信你的理解將越深刻。

委託變數在進行賦值時除了標準的方式,還可以進行簡化:


Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add);
      Worker worker = new Worker();
      int result = worker.HandleTwoNumber(10, 10,method);
//可简化为
// int result = worker.HandleTwoNumber(10, 10,Add);

編譯器會自動檢查Add是否符合TwoNumberHandleMethodDelegate 的定義,如果符合允許直接將方法名賦值給委託變數。

匿名委託

透過上面的範例程式碼,我們很容易發現TwoNumberHandleMethodDelegate method 變數被賦值為Add(Sub),因此在呼叫method(...)時相當於呼叫Add(.....)。這樣一來就可以認為

method與Add完全等效,既然等效那是否可以直接將Add的定義內容賦值給method變數呢?答案是肯定的:


static void Main(string[] args)
    {

      Worker.TwoNumberHandleMethodDelegate method =private static int Add(int a, int b)
    {
      return a + b;
    };
}

但像上面這種生拉硬套是不行的,你還需要做修改。修改內容是:因為現在的程式碼處於Main方法中,存取修飾符去掉,同樣static也應去掉;同時編譯器知道你要給method賦值,那麼要賦的這個值肯定滿足返回類型為int的要求,所有int在此時就多餘了去掉;因為賦值之後method就等效於Add,以後呼叫只要透過method變數就可完成,所有Add方法名稱不需要去掉。如此程式碼變成如下形式:


static void Main(string[] args)
    {

      Worker.TwoNumberHandleMethodDelegate method =  (int a, int b)
    {
      return a + b;
    };
}

經過上面的修改內容簡化了很多,但method賦值的=右端是什麼?此時編譯器並不能正確辨識這是一個方法,因為方法的定義需要滿足包含:存取修身符、傳回型別、方法名、參數清單、方法體五部分內容。雖然你心裡清楚這是個簡化了的方法,但是編譯器不懂你的心.........,那沒關係只要我們告訴編譯器,後面的是個簡化方法就可以了。


static void Main(string[] args)
    {

      Worker.TwoNumberHandleMethodDelegate method =  delegate(int a, int b)
    {
      return a + b;
    };
}

正如你所期望的那樣,現在編譯器已經知道了=右邊是你經過簡化的方法;ok,現在可以正常賦值並使用了。

透過上面的定義我們發現,用delegate標註的簡化方法沒有一個像Add/Sub一樣固定的名字。因此我們稱這種方法叫匿名委託(我習慣稱匿名方式)。

你可能也注意到該匿名委託定義完畢後就賦值給Main程式碼快中的局部變數method,因此當超出method的作用域後,該方法就再也沒有機會呼叫了。這引出了匿名方法、匿名委託、匿名函數它們最常見的用法,即用來定義只需要使用一次的功能代碼。

以上是C#中委託與匿名委託的具體介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn