委派 是 C# 中極重要的概念,廣泛應用於事件、執行緒、回呼等場景。本質上,委派是參考方法的型別。一旦指派方法,委派即擁有該方法完全相同的行為,可像一般方法一樣擁有參數與回傳值。
public delegate void MyDel();MyDel del = new MyDel(obj.Method); 或 C# 2.0 簡寫 MyDel del = obj.Method;del();namespace DelegateDemo
{
// 各類委派宣告
public delegate void MyDel();
public delegate void MyDel2(int num1, int num2);
public delegate string MyDel3(string s);
public delegate string ProcessString(string s);
class Program
{
static void Main(string[] args)
{
TestDel t = new TestDel();
#region 基礎委派實例化與呼叫
MyDel del = new MyDel(t.MyMethod);
del();
// C# 2.0 簡寫
MyDel del4 = t.MyMethod;
del4();
// 靜態方法
del4 = TestDel.MyStaticMethod;
del4();
// 帶參數委派
MyDel2 del2 = t.MyMethod;
del2(10, 20);
// 帶回傳值委派
MyDel3 del3 = t.MyMethod;
Console.WriteLine(del3("abc"));
#endregion
#region 匿名方法
Console.WriteLine("-----匿名方法演示-----");
ProcessString p = delegate(string inputString)
{
return inputString.ToUpper();
};
Console.WriteLine(p("aaaa"));
#endregion
#region 多播委派
Console.WriteLine("-----多播委派演示-----");
MyDel mydel1 = t.MyMethod;
MyDel mydel2 = t.MyMethod2;
MyDel mydel3 = TestDel.MyMethod3;
MyDel allMyDel = mydel1 + mydel2 + mydel3;
allMyDel(); // 依序執行三個方法
allMyDel -= mydel3;
allMyDel(); // 僅執行前兩個
#endregion
#region 委派作為參數
Console.WriteLine("-----委派作為參數-----");
MyDel3 paramMyDel3 = t.MyMethod;
TestDel.MyParamMethod("aaa", paramMyDel3);
#endregion
#region 委派作為回傳值
Console.WriteLine("-----委派作為回傳值-----");
MyDel3 returnMyDel = t.MyReturnMethod();
Console.WriteLine(returnMyDel("sssssssssssss"));
#endregion
}
}
public class TestDel
{
public static void MyStaticMethod() => Console.WriteLine("My Static Method");
public void MyMethod() => Console.WriteLine("MyMethod");
public void MyMethod2() => Console.WriteLine("My Method 22222222222");
public static void MyMethod3() => Console.WriteLine("My Method 3333333333333");
public void MyMethod(int num1, int num2) => Console.WriteLine(num1 + num2);
public string MyMethod(string s) => s.ToUpper();
// 委派作為參數
public static void MyParamMethod(string s, MyDel3 del3) => Console.WriteLine(del3(s));
// 委派作為回傳值
public MyDel3 MyReturnMethod() => MyMethod;
}
}
public delegate void ProcessBook(Book b);
public class BookDB
{
public List books = new List();
public void AddBook(Book b) => books.Add(b);
public void PrintBook(ProcessBook process)
{
foreach (var book in books)
process(book);
}
}
public class MyParamDelegateTest
{
BookDB bookDB = new BookDB();
double total = 0;
public void AddBooks()
{
bookDB.AddBook(new Book { BookID = 1, BookName = "C#", Price = 123, IsPaperbook = true });
bookDB.AddBook(new Book { BookID = 1, BookName = "C#", Price = 123, IsPaperbook = false });
bookDB.AddBook(new Book { BookID = 2, BookName = "ASP.Net", Price = 12, IsPaperbook = true });
bookDB.AddBook(new Book { BookID = 1, BookName = "ADO", Price = 23, IsPaperbook = false });
}
public void TestProcessBook(Book b)
{
if (b.IsPaperbook) Console.WriteLine(b.BookName);
}
public void TotalPrice(Book b) => total += b.Price;
public void MyTest()
{
bookDB.PrintBook(TestProcessBook); // 列印實體書名稱
bookDB.PrintBook(TotalPrice); // 計算總價
Console.WriteLine(total);
}
}
public class Book
{
public int BookID { get; set; }
public string BookName { get; set; }
public double Price { get; set; }
public bool IsPaperbook { get; set; }
}
public delegate int MyReturnDelegate(int num1, int num2);
public class MyCalcuate
{
public MyReturnDelegate Calcuate(string oper)
{
MyReturnDelegate myReturn = null;
switch (oper)
{
case "+": myReturn = delegate(int n1, int n2) { return n1 + n2; }; break;
case "-": myReturn = delegate(int n1, int n2) { return n1 - n2; }; break;
case "*": myReturn = delegate(int n1, int n2) { return n1 * n2; }; break;
case "/": myReturn = delegate(int n1, int n2) { return n1 / n2; }; break;
}
return myReturn;
}
}
public class MyReturnDelegateTest
{
public void MyTest()
{
MyCalcuate myCalcuate = new MyCalcuate();
do
{
Console.WriteLine("請輸入運算符號 (+ - * /)");
string oper = Console.ReadLine();
Console.WriteLine("請輸入運算元 1"); string num1 = Console.ReadLine();
Console.WriteLine("請輸入運算元 2"); string num2 = Console.ReadLine();
MyReturnDelegate myReturn = myCalcuate.Calcuate(oper);
int result = myReturn(int.Parse(num1), int.Parse(num2));
Console.WriteLine($"{num1}{oper}{num2}={result}");
Console.WriteLine("繼續嗎? Y/N");
} while (Console.ReadLine().ToUpper() != "N");
}
}
C# 3.0 引入 Lambda 運算式 (=>) 取代匿名方法,語法更簡潔;C# 內建 Func<T, TResult>、Action<T> 等泛型委派,減少自訂委派宣告。但理解傳統委派機制,仍是掌握事件、LINQ、非同步程式設計的基石。
原文連結:https://www.cnblogs.com/yangyancheng/archive/2011/04/21/2024145.html