委托是一種定義方法簽名的類型。當(dāng)實(shí)例化委托時(shí),您可以將其實(shí)例與任何具有兼容簽名的方法相關(guān)聯(lián)。您可以通過委托實(shí)例調(diào)用方法。
如何使用委托?
1、定義委托類型
[訪問修飾符] ?delegate ?返回類型 ?委托名(形參);
2、聲明委托對象
委托名 委托實(shí)例名;
3、創(chuàng)建委托對象
委托實(shí)例名 = new 委托名(某個(gè)類的方法)
4、使用委托調(diào)用方法
委托實(shí)例名(實(shí)參)
委托注意事項(xiàng):
1、委托和方法必須具有相同的簽名。
2、委托可以調(diào)用多個(gè)方法,即一個(gè)委托對象可以維護(hù)一個(gè)可調(diào)用方法的列表而不是單獨(dú)的一個(gè)方法,稱為多路廣播(多播)。
3、使用+=和-=運(yùn)算實(shí)現(xiàn)方法的注冊和注銷
寫法:
1、委托 ?委托名 ?= ?new ?委托(會調(diào)用的方法名);
? ?? 委托名(參數(shù));
? ??CallobjCall =newCall(SimpleMath.Multiply);
? ?CallobjCall1 =newCall(newSimpleMath().Divide);
2、委托 ?委托名 ?= ?會調(diào)用的方法名;
? ?? 委托名(參數(shù));
? ?CallobjCall =SimpleMath.Multiply;
? ?CallobjCall1 =newSimpleMath().Divide;
3、匿名方法
? ? ? 委托 ?委托名 ?= ?delegate(參數(shù)){會調(diào)用的方法體};
? ? ? 委托名(參數(shù));
? ? ?CallobjCall ?=delegate(inta,intb) {?return?a * b;?};
? ? ?CallobjCall1 =delegate(inta,intb) {?returna / b;?};
4、lambda表達(dá)式
? ? ? 委托 ?委托名 = ((參數(shù)1,。。參數(shù)n)=>{會調(diào)用的方法體});
? ? ? 委托名(參數(shù));
? ??CallobjCall = ((inta,intb) => {returna * b; });
? ??CallobjCall1 = ((inta,intb) => {returna / b; });
5、用Action和Func,第一個(gè)無返回值
? ? ?Func<參數(shù)1, 參數(shù)2, 返回值> 委托名 = ((參數(shù)1,參數(shù)2) => {帶返回值的方法體 });
? ? ?返回值 = 委托名(參數(shù)1,參數(shù)2);
? ??Action obj = ((a, b) => {Console.WriteLine(a * b); });
? ?? obj(5, 3);
? ? ?Func objCall = ((a, b) => {returna * b; });
? ??intresult = objCall(5, 3);
? ??Func objCall1 = ((a, b) => {returna / b; });
? ??intresult1 = objCall1(5, 3);
1.委托的聲明
?(1). delegate
? ?? ? ?delegate是我們常用到的一種聲明。
Delegate至少0個(gè)參數(shù),至多32個(gè)參數(shù),可以無返回值,也可以指定返回值類型。
例:public?delegate?int?MethodtDelegate(int?x,?int?y);表示有兩個(gè)參數(shù),并返回int型。
?(2). Action
? ? ? ? Action是無返回值的泛型委托。
Action表示無參,無返回值的委托。
Action 表示有傳入?yún)?shù)int,string無返回值的委托。
? Action 表示有傳入?yún)?shù)int,string,bool無返回值的委托。
? ? ? ? Action 表示有傳入4個(gè)int型參數(shù),無返回值的委托。
? Action至少0個(gè)參數(shù),至多16個(gè)參數(shù),無返回值。
例:
? ? ? ? public void Test(Action action,T p)
? ? ? ? {
? ? ? ? ? ? ?action(p);
? ? ? ? }
??(3). Func
Func是有返回值的泛型委托
Func 表示無參,返回值為int的委托
Func 表示傳入?yún)?shù)為object,string 返回值為int的委托
Func 表示傳入?yún)?shù)為T1,T2,T3(泛型)返回值為int的委托
Func至少0個(gè)參數(shù),至多16個(gè)參數(shù),根據(jù)返回值泛型返回。必須有返回值,不可void
? ? ? ? 例:
? ? ? ? public int Test(Funcfunc,T1 a,T2 b)
? ? ? ? {
? ? ? ? ? ? ?return func(a, b);
? ? ? ? }
? ?(4) .predicate
predicate是返回bool型的泛型委托
predicate 表示傳入?yún)?shù)為int 返回bool的委托
Predicate有且只有一個(gè)參數(shù),返回值固定為bool
例:public?delegate?bool?Predicate (T obj)
2.委托的使用
(1).Delegate的使用
? ? ? ? public delegate int MethodDelegate(int x, int y);
? ? ? ? private static MethodDelegate method;
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? method = new MethodDelegate(Add);
? ? ? ? ? ? Console.WriteLine(method(10,20));
? ? ? ? ? ? Console.ReadKey();
? ? ? ? }
? ? ? ? private static int Add(int x, int y)
? ? ? ? {
? ? ? ? ? ? return x + y;
? ? ? ? }
(2).Action的使用
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? Test(Run,"Hello World!");
? ? ? ? ? ? Test(Run, 1000);
? ? ? ? ? ? //使用Lambda表達(dá)式定義委托 ? ? ?
? ? ? ? ? ? Test(p => { Console.WriteLine("{0}", p); }, "Hello World"); ? ??
? ? ? ? ? ? Console.ReadKey();
? ? ? ? }
? ? ? ? public static void Test(Action action, T p)
? ? ? ? {
? ? ? ? ? ? action(p);
? ? ? ? }
? ? ? ? private static void Run(string s)
? ? ? ? {
? ? ? ? ? ? Console.WriteLine(s);
? ? ? ? }
? ? ? ? private static void Run(int s)
? ? ? ? {
? ? ? ? ? ? Console.WriteLine(s);
? ? ? ? }
? ?可以使用 Action 委托以參數(shù)形式傳遞方法,而不用顯式聲明自定義的委托。
? ? ? 封裝的方法必須與此委托定義的方法簽名相對應(yīng)。?也就是說,封裝的方法必須具有四個(gè)均通過值傳遞給它的參數(shù),并且不能返回值。
(3).Func的使用
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? Console.WriteLine(Test(Run,100,200));
? ? ? ? ? ? Console.ReadKey();
? ? ? ? }
? ? ? ? public static int Test(Func func, T1 a, T2 b)
? ? ? ? {
? ? ? ? ? ? return func(a, b);
? ? ? ? }
? ? ? ? private static int Run(int a, int b)
? ? ? ? {
? ? ? ? ? ? return a + b;
? ? ? ? }
(4).?predicate的使用
泛型委托:表示定義一組條件并確定指定對象是否符合這些條件的方法。此委托由 Array 和 List 類的幾種方法使用,用于在集合中搜索元素。
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? Point[] points = { new Point(100, 200),
? ? ? ? ? ? new Point(150, 250), new Point(250, 375),
? ? ? ? ? ? new Point(275, 395), new Point(295, 450) };
? ? ? ? ? ? Point first = Array.Find(points, Product);
? ? ? ? ? ? Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
? ? ? ? ? ? Console.ReadKey();
? ? ? ? }
? ? ? ? private static bool Product(Point p)
? ? ? ? {
? ? ? ? ? ? if (p.X * p.Y > 100000)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? }
使用帶有 Array.Find 方法的 Predicate 委托搜索 Point 結(jié)構(gòu)的數(shù)組。如果 X 和 Y 字段的乘積大于 100,000,此委托表示的方法 ProductGT10 將返回 true。Find 方法為數(shù)組的每個(gè)元素調(diào)用此委托,在符合測試條件的第一個(gè)點(diǎn)處停止。
3.委托的清空
(1).在類中申明清空委托方法,依次循環(huán)去除委托引用。
???????? 方法如下:
? ? ? ? public MethodDelegate OnDelegate;? ? ? ? ? ? ? ?
? ? ? ? public void ClearDelegate()? ? ? ?
? ? ? ? {? ? ? ? ? ?
? ? ? ? ? ? while (this.OnDelegate != null)
? ? ? ? ? ? {? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? this.OnDelegate -= this.OnDelegate;?
? ? ? ? ? ? }? ? ? ?
? ? ? ? }
(2).如果在類中沒有申明清空委托的方法,我們可以利用GetInvocationList查詢出委托引用,然后進(jìn)行去除。
方法如下:
? ? ? ???public delegate void MethodDelegate();
? ? ? ? public static MethodDelegate OnDelegate;
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? if (OnDelegate != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Delegate[] dels = test.OnDelegate.GetInvocationList();
? ? ? ? ? ? ? ? for (int i = 0; i < dels.Length; i++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? test.OnDelegate -= dels[i] as MethodDelegate;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
4.委托的特點(diǎn)
委托類似于 C++ 函數(shù)指針,但它們是類型安全的。
委托允許將方法作為參數(shù)進(jìn)行傳遞。
委托可用于定義回調(diào)方法。
委托可以鏈接在一起;例如,可以對一個(gè)事件調(diào)用多個(gè)方法。
方法不必與委托簽名完全匹配。
5.總結(jié):
??Delegate至少0個(gè)參數(shù),至多32個(gè)參數(shù),可以無返回值,也可以指定返回值類型
Func可以接受0個(gè)至16個(gè)傳入?yún)?shù),必須具有返回值
Action可以接受0個(gè)至16個(gè)傳入?yún)?shù),無返回值
Predicate只能接受一個(gè)傳入?yún)?shù),返回值為bool類型