1. Introduction
1.委托⽤于将⽅法作为参数传递给其他⽅法,当于是对具有相同返回类型和参数列表这一类方法进行了封装
2.用关键字delegate 聲明的就是委托
public class TrustFunction
{
public delegate void ShowDelegate();
public void Show()
{
System.Diagnostics.Trace.WriteLine("test");
}
public delegate string ShowStringDelegate(string str);
public string ShowString(string str)
{
return str + "test";
}
}
1.1 Instance
//舊寫法
ShowDelegate showDelegate = new ShowDelegate(test.Show);
//新寫法
ShowDelegate showDelegate = test.Show;
//匿名寫法
ShowDelegate showDelegate = delegate ()
{
Console.WriteLine("匿名委托");
};
//Lambda寫法
ShowDelegate2 showDelegate2 = (string s, int v) => { Console.WriteLine($"{s}&{v}"); };
showDelegate2("s",2);
1.2 Advance
public class DelegateTest
{
// 1.无参数无返回值委托
public delegate void NoReturnNoPara();
// 2.有参数无返回值委托
public delegate void NoReturnWithPara(int x, int y);
// 3.无参数有返回值的委托
public delegate int WithReturnNoPara();
// 4.带参数带返回值的委托
public delegate int WithReturnWithPara(out int x, out int y);
}
class Program
{
private static void NoReturnNoParaMethod()
{
Console.WriteLine("无参数,无返回值的方法");
}
private static void NoReturnWithParaMethod(int s, int t)
{
Console.WriteLine("有参数,无返回值的方法");
}
static void Main(string[] args)
{
DelegateTest.NoReturnNoPara noReturnNoPara= new DelegateTest.NoReturnNoPara(NoReturnNoParaMethod);
//使用赋值的方式实例
DelegateTest.NoReturnWithPara noReturnWithPara = NoReturnWithParaMethod;
//使用匿名委托实例
DelegateTest.WithReturnNoPara withReturnNoPara = delegate()
{
Console.WriteLine("无参数,有返回值的方法");
return default(int);
};
//使用lambda 匿名方法实例
DelegateTest.WithReturnWithPara WithReturnWithPara = (out int x, out int y) =>
{
x = 1;
y = 2;
Console.WriteLine("有参数,有返回值的方法");
return x + y;
};
//调用委托
noReturnNoPara();
//使用invoke调用
noReturnNoPara.Invoke();
//调用有返回值,无参数的委托
int result= withReturnNoPara.Invoke();
//调用有返回值,有参数的委托
int x1, y1;
int result2 = WithReturnWithPara.Invoke(out x1,out y1);
//使用BeginInvoke,开启一个线程去执行委托,NetCore不支持,NetFamework支持
noReturnWithPara.BeginInvoke(1,2,null,null);
//EndInvoke等待BeginInvoke方法执行完成后再执行EndInvoke后面的代码
noReturnWithPara.EndInvoke();
Console.ReadLine();
}
}
2. 委託鏈
- 委托都是继承自MulticastDelegate(多播委托),定义的所有的委托都是多播委托
- 可以通过+=把多个方法添加到这个委托中,形成一个方法的执行链,执行委托的时候,按照添加方法的顺序,依次去执行方法,
- 可以通过-=把加入到委托中的方法注销
- action.BeginInvoke();会开启一个新的线程 去执行委托,注册有多个方法的委托,不能使用BeginInvoke
- 注册有多个方法的委托想要开启新线程去执行委托,可以通过action.GetInvocationList()获取到所有的委托,然后循环,每个方法执行的时候可以BeginInvoke
2.1 Demo
老師讓學生去買東西
public class Student
{
public delegate void BuySomethingDelegate();
public void BuyWater()
{
Console.WriteLine("买水!");
}
public void BuyKFC()
{
Console.WriteLine("买肯德基");
}
public void BuyHotDog()
{
Console.WriteLine("买热狗");
}
}
老師讓學生去買水
Student stu = new Student();
BuySomethingDelegate bsd = new BuySomethingDelegate(stu.BuyWater);
bsd.Invoke();
老師讓學生去買水後,又去買熱狗和漢堡,發現錢不夠,又把熱狗退掉了。
Student stu = new Student();
BuySomethingDelegate bsd = new BuySomethingDelegate(stu.BuyWater);
bsd += stu.BuyHotDog;
bsd += stu.BuyKFC;
bsd -= stu.BuyHotDog;
bsd.Invoke();
2.2 擴展
使用多播委托的时候可能会遇到一个问题,當第一个方法报错了,导致后面的注册的方法都无法调用
//获取委托链上的调用列表,返回的是委托数组
Delegate[] delegateArr= bsd.GetInvocationList();
foreach (BuySomethingDelegate item in delegateArr)
{
try
{
item.Invoke();
}
catch (Exception)
{
Console.WriteLine($"{item.Method.Name}方法报错了!");
}
}
如何取出里面返回值
#如果BuySomethingDelegate 是有返回值的委托,
Delegate[] delegateArr= bsd.GetInvocationList();
foreach (BuySomethingDelegate item in delegateArr)
{
try
{
int result= item.Invoke();
}
catch (Exception)
{
Console.WriteLine($"{item.Method.Name}方法报错了!");
}
}
判断调用的委托是否为空,加加減減可能為空,为空则不会执行,不为空才会执行
Student stu = new Student();
BuySomethingDelegate bsd = new BuySomethingDelegate(stu.BuyWater);
bsd += stu.BuyHotDog;
bsd += stu.BuyKFC;
bsd -= stu.BuyHotDog;
bsd?.Invoke();
3. 泛型
3.1 泛型委託
//定义了具有两个泛型参数类型的委托
public delegate void CustomDelegate<T, V>(T t, V v);
public class TestCustomDelegate
{
//聲明委托变量
CustomDelegate<string, string> customDelegate;
//编写与委托对应的方法
public void TestMethod(string a,string b)
{
Console.WriteLine($"{a}拼接{b}");
}
public void Result()
{
//多種實例化方法
customDelegate = TestMethod;
customDelegate = new CustomDelegate<string, string>(TestMethod);
customDelegate = delegate (string a1, string b1) { Console.WriteLine("delegate匿名方法也可以"); };
customDelegate = (string a2, string b2) => { Console.WriteLine("使用lambda匿名方法"); };
//执行委托
customDelegate("test1","test2");
customDelegate.Invoke("test1", "test2");
}
}
3.2 Action
-
Action 表示无参,无返回值的委托
-
Action<int,string> 表示有参,无返回值的泛型委托,最多可入参16个
-
使用Action 就可以囊括所有无返回值委托,可以说Action事对无返回值委托的进一步包装
public class ActionTest
{
public Action action;
public void SendMsg()
{
Console.WriteLine("消息完成发送");
}
public void Test()
{
//实例化方式有四种,如下
action = SendMsg;
action = new Action(SendMsg);
action = delegate(){ Console.WriteLine("delegate 匿名方法"); };
action = () => { Console.WriteLine("lambda 匿名方法"); };
//调用方式
action();
action.Invoke();
}
}
3.2 Func
-
Func 表示有返回值的委托(必须有返回值)
-
Func可以无参数,也可以有参数,最多16个参数,最后一个表示返回值且只有一个
-
使用方法同delegate,Func不过是对所有的有返回值的数据进行了一个包装
public class FuncTest
{
public Func<int,int> func;
public int DoubleNumber(int number)
{
Console.WriteLine("计算完成");
return number * 2;
}
public void Test()
{
//实例化有以下4种方式
func = DoubleNumber;
func = new Func<int, int>(DoubleNumber);
func = delegate (int a)
{
Console.WriteLine("delegate 匿名方法");
return a * 2 ;
};
func = (int b) =>
{
Console.WriteLine("lambda 匿名方法");
return b * 2;
};
//调用
int result = func(10);
int result2 = func.Invoke(10);
}
}