ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c#图解教程_第十三章& 第十四章_委托和事件

2021-08-02 17:02:55  阅读:167  来源: 互联网

标签:委托 c# Demo void 事件 第十三章 new 图解 public


 

委托


 

定义:委托是持有一个或多个方法的对象,委托是类型,不是对象。

delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与它的签名相匹配的方法的引用"。

 

声明委托


 声明委托的三个步骤

  1. 声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。
  2. 创建delegate对象,并"将你想要传递的函数作为参数传入"。
  3. 在要实现异步调用的地方,通过上一步创建的对象来调用方法。

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有