c#图解教程_第十三章& 第十四章_委托和事件
作者:互联网
委托
定义:委托是持有一个或多个方法的对象,委托是类型,不是对象。
delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与它的签名相匹配的方法的引用"。
声明委托
声明委托的三个步骤
- 声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。
- 创建delegate对象,并"将你想要传递的函数作为参数传入"。
- 在要实现异步调用的地方,通过上一步创建的对象来调用方法。
PS:使用的是设计模式中的观察者模式
public void delegate MyDelegate(); public static void Main(){ MyDelegate dele = new MyDelegate(TestFun); } public void TestFun(){ Console.WriteLine("Hello World"); }
事件
定义:事件处理是一种特殊签名的委托
事件的本质是对委托的封装,类似属性是对字段的封装
事件MydelegateHandle 其实是对委托MyDelegate的一个实例,引发事件处理的通常被编写成一个函数
我们定义事件处理程序DelegateFun(),并把他注册到MydelegateHandle事件中
事件处理程序的参数应该和事件委托相同,一般情况下,事件处理程序接受两个参数,一个是事件的发送者Sender,一个是事件参数e,事件参数e用于在发送者和接受者之间传递消息
public delegate void MyEventHandle(object sender,MyEventArgs e); public class EventTest{ //定义委托 public void delegate MyDelegate();
//定义事件 public event MyDelegate MydelegateHandle;
//定义事件发布者 public void GetEventHandle(){ Console.WriteLine("Test") if(MydelegateHandle!=null){ MydelegateHandle.Invoke(); } } } public class Demo{
//定义事件触发方法 public void DelegateFun(){ Console.WriteLine("Hello EventHandle); } public static void Main(){ EventTest test = new EventTest(); test.MyDelegateHandle += Demo; //直接标书方法名,无需括号 test.GetEventHandle(); //输出 → Test Hello EventHandle } }
事件参数的设置:EventArgs
public class EventTest{ //定义委托 public delegate void MyDelegate(object o,EventArges e); //定义事件,封装委托 public event MyDelegate MyDelegateHandle; //定义事件发布者 public void Demo(DemoEventArgs Dargs){ Conosle.WriteLine($"{Dargs.number}"); if(MyDelegateHandle!=null){ MyDelegateHandle.Invoke(this,Dargs); } } }
//自定义事件参数 public class DemoEventArgs:EventArgs{
public int number; public DemoEventArgs (int number){ this.number = number; } } public class Demo{ //设置事件接受者 public void AcceptEvent(object o,DemoEventArgs args){ Console.WriteLine($"Accept:{args.number}"); } } public class Test{ public static void Main(){ EventTest test = new EventTest(); test.MyDelegateHandle += new Demo().AcceptEvent; test.Demo(new DemoEventArgs(3)); } }
}
同步委托调用和异步委托调用
委托的涉及到的涉及模式是观察者模式。
Observer设计模式是为了定义对象间一对多的依赖关系,以便于当一个对象改变状态时,其他依赖于他的对象会被自动告知并更新,观察者模式是一种松耦合的设计模式
大多数的委托的返回值都是void,原因是观察者设计模式本身就是松耦合的关系,发布者不关心谁订阅了事件,更不关心事件的返回值,所以大多数委托的范围值为空
订阅方法和取消订阅方法
public class Sender{ //定义委托 public delegate void MyDelegate(); //定义事件封装委托 public event MyDelegate MyDelegateHandle; //事件发布者 public void SendMethod(){
//委托调用的方式是同步调用委托 if(MyDelegateHandle!=null){ MyDelegateHandle.Invoke(); } } }
//订阅客户端类 public class Demo{ public void TestOne(){ Console.WriteLine("TestOne"); } public void TestTwo(){ Console.WriteLine("TestTwo"); } } // public class DemoTest{ public static void Main(){ Sender sen = new Sender(); //订阅客户端,使用符号 "+=" 订阅客户端 sen.SendMethod += new Demo().TestOne(); sen.SendMethod += new Demo().TestTwo(); //取消订阅,使用符号 "-=",取消订阅客户端 sen.SendMethod -=new Demo().TestOne(); sen. SendMethod(); //输出结果 TestTwo; //每次只订阅一个客户端,使用符号“=” sen.SendMethod = new Demo().TestOne; sen.SendMethod(); //输出结果TestOne //每次使用 = 都相当于重新订阅客户端,而不是累加 sen.SendMethod = new Demo().TestTwo(); //输出结果TestTwo } }
同步调用委托 订阅的客户端会影响发布者所在的程序,当订阅的客户端发生异常,会将返回异常往上抛,使得程序异常结束,即时我们使用了catch块捕获了异常,但未执行的订阅者将不会继续执行
我们采取异步委托调用的方式,订阅的客户端不能影响事件的发布者,所以我们采取委托中的GetInvocationList的方法获取订阅的所有客户端的返回值
//不接受返回值 public void DoSomething() { // 做某些其他的事情 if (MyEvent != null) { Delegate[] delArray = MyEvent.GetInvocationList(); foreach (Delegate del in delArray) { try { // 使用DynamicInvoke方法触发事件 del.DynamicInvoke(this, EventArgs.Empty); } catch (Exception e) { Console.WriteLine("Exception: {0}", e.Message); } } } } //若订阅的方法具有返回值 public static object[] DoSomething(){ //做某些事情 if(MyEvent !=null){ Delegate[] delArray = MyEvent.GetInvocationList(); List<Object> objList = new List<Object>(); foreach(Delegate method in delArray){ try{ // 使用DynamicInvoke方法触发事件 object obj = method.DynamicInvoke(args); if (obj != null) objList.Add(obj); }catch(exception ex){ Console.WriteLine(ex.Message); } } return objList.ToArray(); } }
//异步循环调用
public class Publisher {
public delegate void EventHandler();
public event EventHandler MyEvent;
public void DoSomething() {
// 做某些其他的事情
Console.WriteLine("DoSomething invoked!");
if (MyEvent != null) {
Delegate[] delArray = MyEvent.GetInvocationList();
foreach (Delegate del in delArray) {
EventHandler method = (EventHandler)del;
IAsyncResult asyncResult= method.BeginInvoke(null, EventArgs.Empty, null, null);
object rtn = method.EndInvoke(asyncResult); //输出返回值,结束异步调用
}
}
}
}
单个异步委托调用
public delegate string MyDelegate3(string name); public class Demo{ public string DemoTest(string name){ return name; } } public class Send{ public static void Main(){ MyDelegate3 delegate3 = new MyDelegate3(new Demo().DemoTest); IAsyncResult asyncResult=delegate3.BeginInvoke("Jack", null,null); //异步调用 string rtn = delegate3.EndInvoke(asyncResult); //输出返回值,结束异步调用 } }
标签:委托,c#,Demo,void,事件,第十三章,new,图解,public 来源: https://www.cnblogs.com/FrameCode/p/15080811.html