Delegate
-
-
- 1.什么是委托
- 2.委托概述
- 3.聲明委托類型
- 4.創建委托對象
- 5.給委托賦值
- 6.組合委托
- 7.為委托添加/移除方法
- 8.調用委托
- 9.委托的示例
- 10.調用帶返回值的委托
- 11.調用帶引用參數的委托
- 12.匿名方法
- 12.1 使用匿名方法
- 12.2 匿名方法的語法
- 12.2.1 返回類型
- 12.2.2 參數
- 12.2.3 params參數
- 13.Lambda表達式
- 14.常見泛型委托
- 14.1 Action
- 14.2 Func
- 14.3 Predicate
-
1.什么是委托
可以認為委托是持有一個或多個方法的對象,此對象可以執行它所“持有”的方法。
delegate void Del(int value); class Program { static int a = 1; static void Up(int v) { Console.WriteLine($"{a + v}"); } static void Down(int v) { Console.WriteLine($"{a - v}"); } static void Main() { Del del1 = new Del(Up); Del del2 = new Del(Down); del1(1); del2(1); Console.ReadKey(); }output
2 02.委托概述
使用委托與類的比較,入下圖:
可以把委托看作是包含有序方法列表的對象,這些方法具有相同的簽名和返回類型:
- 方法的列表稱為調用列表
- 委托保存的方法可以來自任何類或結構,只有匹配一下兩點:
- 委托的返回類型
- 委托的簽名(包括ref和out修飾符)
- 調用列表中的方法可以是實例方法也可以是靜態方法
- 在調用委托時,會執行其調用列表中的所有方法
3.聲明委托類型
委托類型定義了委托對象調用列表中允許的方法的形式,如下示例代碼聲明了委托類型:
delegate void MyDel( int x ); // delegate為關鍵字,void為返回類型,MyDel為委托類型名,int為簽名委托聲明與方法聲明的不同:
- 以delegate關鍵字開頭
- 沒有方法主體
- 不需要在類內部聲明,因為它是類型聲明
4.創建委托對象
委托類型的變量聲明如下:
MyDel delVar;有兩種創建委托對象的方式,第一種是使用new運算符, new運算符的操作數組成如下:
- 委托類型名
- 一組圓括號,其中包含作為調用列表中的第一個成員的方法的名字
還可以使用以下快捷語法創建委托對象:
delVar = Class1.Method1;5.給委托賦值
由于委托時引用類型,可以通過賦值來改變包含在委托變量中的引用,舊的委托對象會被垃圾回收器回收。
MyDel delVar; delVar = Class1.Method1; delVar = Class1.Method2; // Class1.Method1將會被GC6.組合委托
委托可以調用額外的運算符來“組合”。
MyDel delA = Class1.Method1; MyDel delB = Class1.Method2; MyDel delC = delA + delB; // 組合調用列表7.為委托添加/移除方法
使用+=運算符為委托添加方法:
MyDel delA = Class1.Method1; // 創建并初始化 delA = Class2.Method2; // 增加方法 delA = StaticClass.StaticMethod; // 增加方法由于委托是不可變的,所以每添加一個方法其實是創建了一個新的委托。 使用-=運算符為委托移除方法:
delA -= Class2.Method2; // 從委托移除方法移除一個方法同樣是創建了一個新的委托。 移除委托時的注意事項:
- 如果再調用列表中有多個相同的方法,將從列表最后開始搜索,并移除第一個匹配方法
- 試圖刪除委托中不存在的方法沒有效果
- 試圖調用空委托會拋出異常,若調用列表為空,則委托是null
8.調用委托
可以向調用方法一樣簡單的調用委托。
Mydel delVar = inst.MyM1; delVar += SCl.m3; delVar += X.Act; ... delVar(55);在使用參數調用委托時會使用相同的參數值(如55)。
9.委托的示例
delegate void PrintFunction(); class Test { public void Print1() { Console.WriteLine("Print1 -- instance"); } public static void Print2() { Console.WriteLine("Print2 -- static"); } } class Program { static void Main() { Test t = new Test(); PrintFunction pf = t.Print1; pf += Test.Print2; pf += t.Print1; pf += Test.Print2; if(null!=pf) { pf(); } else { Console.WriteLine("Delegate is empty"); } Console.ReadKey(); } }output
Print1 -- instance Print2 -- static Print1 -- instance Print2 -- static10.調用帶返回值的委托
delegate int MyDel(); class MyClass { int value = 5; public int Add2() { value += 2; return value; } public int Add3() { value += 3; return value; } } class Program { static void Main() { MyClass mc = new MyClass(); MyDel md = mc.Add2; md += mc.Add3; md += mc.Add2; Console.WriteLine($"value = {md()}"); Console.ReadKey(); } }output
value = 12最后一個方法執行的返回值是委托的返回值。
11.調用帶引用參數的委托
在調用委托列表中的下一個方法時,參數的新值回傳給下一個方法
delegate void MyDel(ref int x); class MyClass { public void Add2(ref int x) { x += 2; } public void Add3(ref int x) { x += 3; } static void Main() { MyClass mc = new MyClass(); MyDel md = mc.Add2; md += mc.Add3; md += mc.Add2; int x = 5; md(ref x); Console.WriteLine($"value = {x}"); Console.ReadKey(); } }output
value = 1212.匿名方法
匿名方法是在初始化委托時內聯聲明的方法。
12.1 使用匿名方法
- 聲明委托變量時作為初始化表達式
- 組合委托時在賦值語句的右邊
- 為委托增加事件時在賦值語句的右邊
12.2 匿名方法的語法
匿名方法表達式的語法包含以下組成部分:
- delegate類型關鍵字
- 參數列表,無參可省略
- 語句塊,包含匿名方法的代碼
12.2.1 返回類型
若委托的返回類型為int,則匿名方法中也應返回int。
delegate int Del(int n); static void Main() { Del d = delegate(int x) { return x + 20; } // 返回一個整型值 }12.2.2 參數
除了數組參數,匿名方法的參數列表必須與委托有以下匹配:
- 參數數量
- 參數類型及位置
- 修飾符 以下兩個情況都滿足可以簡化匿名方法的參數列表:
- 委托的參數列表不包含任何out參數
- 匿名方法不使用任何參數
12.2.3 params參數
如果委托聲明的參數列表包含params參數,那么匿名方法的參數列表將忽略params關鍵字:
delegate void Del(int x, params in[] y); Del d = delegate(int x, int[] y) delegate void MyDel(int x, params int[] y); class MyClass { static void Main() { MyDel md = delegate (int x, int[] y) { foreach(var i in y) { Console.WriteLine(i); } }; md(1, 2, 3, 4); Console.ReadKey(); } }output
2 3 413.Lambda表達式
使用Lambda表達式創建委托:
MyDel del = delegate(int x) {return x + 1;}; // 匿名方法 MyDel newdel = (int x) => {return x + 1;}; // Lambda表達式Lambda表達式的簡化規則:
- 編譯器可從委托聲明中得到委托參數的類型(ref和out參數須注明類型)
- 帶有類型的參數列表稱為顯示類型
- 省略類型的參數列表稱為隱式類型
- 如果只有一個隱式類型參數,則可以省略圓括號
- Lambda允許表達式主體是語句塊或表達式 Lambda表達式的語法演示如下:
Lambda表達式的語法由Lambda運算符和左邊的參數部分以及右邊的Lambda主體構成。
14.常見泛型委托
14.1 Action
Action<>委托可以擁有n個參數(0-16),無返回值。
class Program {static void Method1() { Console.WriteLine("without any parameter"); } static void Method2(int i) { Console.WriteLine($"the int is {i}"); } static void Method3(string s, double d) { Console.WriteLine($"the string is {s}, the double is ze8trgl8bvbq"); } static void Main() { Action A1 = Method1; Action<int> A2 = Method2; Action<string, double> A3 = Method3; A1(); A2(1); A3("hello", 3.14); Console.ReadKey(); } }output
without any parameter the int is 1 the string is hello, the double is 3.1414.2 Func
Func<>委托可以擁有n個參數(1-16),類型參數中的最后一個作為返回值類型。因此類型參數不能為空,至少有一個返回類型。
class Program {static int Method1(int i) { return i * 10; } static string Method2(int a, double d) { return (a + d).ToString(); } static void Main() { Func<int, int> F1 = Method1; Func<int, double, string> F2 = Method2; Console.WriteLine($"{F1(10)}"); Console.WriteLine($"{F2(1, 3.14)}"); Console.ReadKey(); } }output
100 4.1414.3 Predicate
Predicate<>委托擁有一個參數,其返回值為bool型。
class Program {static bool Method(int i) { return i > 0 ? true : false; } static void Main() { Predicate<int> P = Method; Console.WriteLine(P(10)); Console.ReadKey(); } }output
True通過匿名方法使用Predicate<>,
class Program {static void Main() { var anomynous = new Predicate<int>(delegate (int i) { return i > 0 ? true : false; }); Console.WriteLine(anomynous(1)); Console.ReadKey(); } }output
True轉載于:https://www.cnblogs.com/jizhiqiliao/p/10649160.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: dtoj#4263. duliu
- 下一篇: 题解 P1091 【合唱队形】