C#之委託概要(Delegate)


1、C#委託是什麼?(Delegate)

C# 中的委託(Delegate)類似於 C 或 C++ 中函數的指針。委託(Delegate) 是存有對某個方法的引用的一種引用類型變量。引用可在運行時被改變。

委託(Delegate)特別用於實現事件和回調方法。所有的委託(Delegate)都派生自 System.Delegate 類。

我們知道,委託是方法的抽象,它存儲的就是一系列具有相同簽名和返回值類型的方法的地址。調用委託的時候,委託包含的所有方法將被執行。

2、聲明委託

委託聲明決定了可由該委託引用的方法。委託可指向一個與其具有相同標籤的方法。
例如,假設有一個委託:

public delegate void NoReturnWithPara(string s);

上面的委託可被用於引用任何一個帶有一個單一的 string 參數,且無返回值的方法。

聲明委託的語法如下:

delegate <return type> <delegate-name> <parameter list>

3、實例化委託

一旦聲明瞭委託類型,委託對象必須使用 new 關鍵字來創建,且與一個特定的方法有關。當創建委託時,傳遞到 new 語句的參數就像方法調用一樣書寫,但是不帶有參數。例如:

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);	//傳入的是方法名
printString ps2 = new printString(WriteToFile);		//同上

下面的實例演示了委託的聲明、實例化和使用,該委託可用於引用帶有兩個整型參數的方法,並返回一個整型值。

using System;

namespace MyDelegate
{
	/// <summary>
    /// 委託:是一個類,繼承自System.MulticastDelegate,裏面內置了幾個方法
    /// </summary>
    public delegate int WithReturnWithPara(int x, int y);
	
	public class DelegateDemo
	{
		static int num = 10;
		public static int AddNum(int p, int n)
        {
        	num += p + n;
        	return num;
        }
		public static int MultNum(int q, int m)
      	{
         	num *= q * m;
         	return num;
      	}
      	public static int getNum()
      	{
         	return num;
      	}
		
		static void Main(string[] args)
		{
			// 創建委託實例
			WithReturnWithPara dl1 = new WithReturnWithPara(AddNum);
			WithReturnWithPara dl2 = new WithReturnWithPara(MultNum);
			// 使用委託對象調用方法
			dl1(2, 3);
			Console.WriteLine("num 值爲: {0}", getNum());
			dl2.Invoke(2, 3);
			Console.WriteLine("num 值爲: {0}", getNum());
			Console.ReadKey();
		}
	}
}

當上面的代碼被編譯和執行時,它會產生下列結果:

num 值爲: 15
num 值爲: 90

4、委託的多播(Multicasting of a Delegate)

委託對象可使用 “+” 運算符進行合併。一個合併委託調用它所合併的兩個委託。只有相同類型的委託可被合併。"-" 運算符可用於從合併的委託中移除組件委託。invoke的時候可以按順序執行

使用委託的這個有用的特點,您可以創建一個委託被調用時要調用的方法的調用列表。這被稱爲委託的 多播(multicasting),也叫組播。下面的程序演示了委託的多播:

using System;

namespace MyDelegate
{
	/// <summary>
    /// 委託:是一個類,繼承自System.MulticastDelegate,裏面內置了幾個方法
    /// </summary>
    public delegate int WithReturnWithPara(int x, int y);
	
	public class DelegateDemo
	{
		static int num = 10;
		public static int AddNum(int p, int n)
        {
        	num += p + n;
        	return num;
        }
		public static int MultNum(int q, int m)
      	{
         	num *= q * m;
         	return num;
      	}
      	public static int getNum()
      	{
         	return num;
      	}
		
		static void Main(string[] args)
		{
			// 創建委託實例
			WithReturnWithPara dl;
			WithReturnWithPara dl1 = new WithReturnWithPara(AddNum);
			WithReturnWithPara dl2 = new WithReturnWithPara(MultNum);
			dl = dl1;
			dl += dl2;
			//調用多播
			dl(2, 3);
			Console.WriteLine("num 值爲: {0}", getNum());
			Console.ReadKey();
		}
	}
}

以上代碼的執行結果:

num 值爲: 90

5、匿名方法

匿名方法是在初始化委託時內聯聲明的方法。
基本結構:

deleage( 參數 ) { 語句塊 }

例如:

delegate int MyDel (int x); //定義一個委託 

MyDel del = delegate(int x){ return x; };

6、Lambda表達式

Lambda表達式主要用來簡化匿名方法的語法。在匿名方法中,delegate關鍵字有點多餘,因爲編譯器已經知道我們將方法賦值給委託。通過幾個簡單步驟,我們就可以將匿名方法轉換爲Lambda表達式:

刪除delegate關鍵字
在參數列表和匿名方法主體之間防Lambda運算符=>。Lambda運算符讀作"goes to"。

MyDel del = delegate(int x) { return x; };//匿名方法
MyDel del2 = (int x) => {return x;};//Lambda表達式
MyDel del3 = x => {return x};//簡寫的Lambda表達式

7、泛型委託

如果你知道泛型,那麼就很容易理解泛型委託,說白了就是含有泛型參數的委託,例如:

public delegate T Calculator<T> (T arg);

場景使用,如下:

public delegate T Calculator<T>(T arg);
class Program {
    static int Double(int x) { return x * 2; }
    static void Main(string[] args) {
        int[] values = { 1, 2, 3, 4 };
        Utility.Calculate(values, Double);

        foreach (int i in values){
            Console.Write(i + " "); // 2 4 6 8
        	Console.ReadKey();
        }
    }
}
class Utility {
    public static void Calculate<T>(T[] values, Calculator<T> c) {
        for (int i = 0; i < values.Length; i++)
            values[i] = c(values[i]);
    }
}

8、Func 和 Action委託

泛型委託,能適用於任何返回類型和任意參數(類型和合理的個數)的通用委託。

以下的 in 表示參數,out 表示返回結果

Func委託:有返回值的泛型委託

delegate TResult Func<out TResult> ();
delegate TResult Func<in T, out TResult> (T arg);
delegate TResult Func<in T1, in T2, out TResult> (T1 arg1, T2 arg2);
... 一直到 T16

Action委託:無返回值的泛型委託

delegate void Action ();
delegate void Action <in T> (T arg);
delegate void Action <in T1, in T2> (T1 arg1, T2 arg2);
... 一直到 T16

Func 和 Action 委託,除了ref參數和out參數,基本上能適用於任何泛型委託的場景,非常好用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章