请教各位大哥,为什么要使用事件?有什么好处吗?调用方法多方便呀?非要做个事件,通过事件去找委托,通过委托调用方法,有什么意义?
是因为不同的设备之间有的时候不能直接调用方法,有限制,所以才出现了事件这个东西吗?
还是有更深层次的意义?
谢谢各位大哥了,通俗点解释。
学生问我的,我也不懂,没做过项目,见笑了。呵呵

解决方案 »

  1.   

    在google中,你搜索:C# + 委托+事件,就会出好多你想要的,其中有几个博客园中的帖子写的很好,推荐你去看看。。
      

  2.   

    举个简单例子,类A中有类B的一个实例成员,
    当B执行完某个函数,需要回调A的一个事件处理函数,你不用委托的方式实现,
    用方法怎么做?
      

  3.   

    浅析C#的事件处理和自定义事件一、了解C#中的预定义事件处理机制    在写代码前我们先来熟悉.net框架中和事件有关的类和委托,了解C#中预定义事件的处理。    EventArgs是包含事件数据的类的基类,用于传递事件的细节。    EventHandler是一个委托声明如下         public delegate void EventHandler( object sender , EventArgs e )    注意这里的参数,前者是一个对象(其实这里传递的是对象的引用,如果是button1的click事件则sender就是button1),后面是包含事件数据的类的基类。    下面我们研究一下Button类看看其中的事件声明(使用WinCV工具查看),以Click事件为例。         public event EventHandler Click;    这里定义了一个EventHandler类型的事件Click    前面的内容都是C#在类库中已经为我们定义好了的。下面我们来看编程时产生的代码。        private void button1_Click(object sender, System.EventArgs e)
            {
                ...
            }    这是我们和button1_click事件所对应的方法。注意方法的参数符合委托中的签名(既参数列表)。那我们怎么把这个方法和事件联系起来呢,请看下面的代码。        this.button1.Click += new System.EventHandler(this.button1_Click);    把this.button1_Click方法绑定到this.button1.Click事件。    下面我们研究一下C#事件处理的工作流程,首先系统会在为我们创建一个在后台监听事件的对象(如果是 button1的事件那么监听事件的就是button1),这个对象用来产生事件,如果有某个用户事件发生则产生对应的应用程序事件,然后执行订阅了事件的所有方法。二、简单的自定义事件(1)    首先我们需要定义一个类来监听客户端事件,这里我们监听键盘的输入。    定义一个委托。        public delegate void UserRequest(object sender,EventArgs e);    前面的object用来传递事件的发生者,后面的EventArgs用来传递事件的细节,现在暂时没什么用处,一会后面的例子中将使用。    下面定义一个此委托类型类型的事件        public event UserRequest OnUserRequest;    下面我们来做一个死循环        public void Run()
          {
          bool finished=false;
          do
          {
           if (Console.ReadLine()=="h")
           {
            OnUserRequest(this,new EventArgs());
           }  
          }while(!finished);
          }    此代码不断的要求用户输入字符,如果输入的结果是h,则触发OnUserRequest事件,事件的触发者是本身(this),事件细节无(没有传递任何参数的EventArgs实例)。我们给这个类取名为UserInputMonitor。   下面我们要做的是定义客户端的类
        首先得实例化UserInputMonitor类       UserInputMonitor monitor=new UserInputMonitor();    然后我们定义一个方法。       private void ShowMessage(object sender,EventArgs e)
          {
              Console.WriteLine("HaHa!!");
          }     最后要做的是把这个方法和事件联系起来(订阅事件),我们把它写到库户端类的构造函数里。     Client(UserInputMonitor m)
         {
          m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
          //m.OnUserRequest+=new m.UserRequest(this.ShowMessage);      //注意这种写法是错误的,因为委托是静态的     }     下面创建客户端的实例。         new Client(monitor);     对了,别忘了让monitor开始监听事件。        monitor.run();     大功告成,代码如下:        using System;
            class UserInputMonitor
            {
             public delegate void UserRequest(object sender,EventArgs e);
             //定义委托
             public event UserRequest OnUserRequest;
             //此委托类型类型的事件
             public void Run()
             {
              bool finished=false;
              do
              {
               if (Console.ReadLine()=="h")
               {
                OnUserRequest(this,new EventArgs());
               }  
              }while(!finished);
             }
            }
                        public class Client
            {
             public static void Main()
             {
              UserInputMonitor monitor=new UserInputMonitor();
              new Client(monitor);
              monitor.Run();
             }
             private void ShowMessage(object sender,EventArgs e)
             {
              Console.WriteLine("HaHa!!");
             }
             Client(UserInputMonitor m)
             {
              m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
              //m.OnUserRequest+=new m.UserRequest(this.ShowMessage);
              //注意这种写法是错误的,因为委托是静态的
             }
            }三、进一步研究C#中的预定义事件处理机制    可能大家发现在C#中有些事件和前面的似乎不太一样。例如      private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
          {      }      this.textBox1.KeyPress+=newSystem.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);    这里使用了KeyPressEventArgs而不是EventArgs作为参数。这里使用了KeyEventHandler委托,而不是EventHandler委托。    KeyPressEventArgs是EventArgs的派生类,而KeyEventHandler的声明如下      public delegate void KeyEventHandler( object sender , KeyEventArgs e );   是参数为KeyEventArgs的委托。那为什么KeyPress事件要这么做呢,我们可以从两个类的构造函数来找答案。       public EventArgs();       public KeyPressEventArgs(char keyChar);    这里的keyData是什么,是用来传递我们按下了哪个键的,哈。    我在KeyEventArgs中又发现了属性       public char KeyChar { get; }    进一步证明了我的理论。下面我们来做一个类似的例子来帮助理解。四、简单的自定义事件(2)    拿我们上面做的例子来改。    我们也定义一个EventArgs(类似KeyEventArgs)取名MyEventArgs,定义一个构造函数public MyEventArgs(char keyChar),同样我们也设置相应的属性。代码如下    using System;
        class MyMyEventArgs:EventArgs
        {
         private char keyChar;
         public MyMyEventArgs(char keyChar)
         {
          this.keychar=keychar;
         }
         public char KeyChar
         {
          get
          {
           return keyChar;
          }
         }
        }因为现在要监听多个键了,我们得改写监听器的类中的do...while部分。改写委托,改写客户端传递的参数。好了最终代码如下,好累    using System;
        class MyEventArgs:EventArgs
        {
         private char keyChar;
         public MyEventArgs(char keyChar)
         {
          this.keyChar=keyChar;
         }
         public char KeyChar
         {
          get
          {
           return keyChar;
          }
         }
        }
              class UserInputMonitor
        {
         public delegate void UserRequest(object sender,MyEventArgs e);
         //定义委托
         public event UserRequest OnUserRequest;
         //此委托类型类型的事件
         public void Run()
         {
          bool finished=false;
          do
          {
           string inputString= Console.ReadLine();
           if (inputString!="") 
            OnUserRequest(this,new MyEventArgs(inputString[0]));
          }while(!finished);
         }
        }          public class Client
        {
         public static void Main()
         {
          UserInputMonitor monitor=new UserInputMonitor();
          new Client(monitor);
          monitor.Run();
         }
         private void ShowMessage(object sender,MyEventArgs e)
         {
          Console.WriteLine("捕捉到:{0}",e.KeyChar);
         }
         Client(UserInputMonitor m)
         {
          m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
          //m.OnUserRequest+=new m.UserRequest(this.ShowMessage);
          //注意这种写法是错误的,因为委托是静态的
         }
        }
      

  4.   


    事件一般和委托一起使用的
    委托是个好东西的
    不知道LZ对委托了解多少
    不清楚的话去我的空间下载视频教程是MSDN 的 WebCast
    狠经典的
      

  5.   

    我认为事件主要是一种面向对象思想的体现,class A{
     B b;
    }
    class B{
     A a;
    }双向引用的情况下,双方的公在方法全部暴露给对方,不需要单向引用时的回调,但是这可能仍然无法体现事件是独特作用...class A{
     public event Action<A> Teste;
     protected virtual void OnTeste()
     {
       if(this.Teste!=null)this.Teste(this);
     }
     int data;
     public int Data
     {
      get{return this.data;}
      set{
        this.data=value;
        if(data>10)this.OnTeste();
       }
     }
    }
    //上面从设计的角度而言,这样写意味着,类A的开发者,仅需要确定一个方法的触发条件
    而不关心方法的具体实现.这种设计是仅用普通方法所达不到的,在现实在我们可能会
    遇到这样的设计情况,因此从面向对象的设计思想出发,事件的出现显得很自然,也很合理.当把A给于不同的客户端时这种作用就会得以显现:客户端B,和Cclass B{
      static void Main(){
        B b=new B();
      try{
        B.a.Data= Convert.ToInt32(Console.ReadLine());//事件的触发处
       }
       catch{}
     }
     A a;
     a.Teste+=C_M1;
     static void C_M1(A a)
     {
       Console.WriteLine("嗨!我是客户端B...!");//A处
     }
    }
    //------------
    class C{
      static void Main(){
      C c=new C();
      try{
        C.a.Data= Convert.ToInt32(Console.ReadLine());//事件的触发处
       }
       catch{}
     }
     A a;
     a.Teste+=C_M1;
     static void C_M1(A a)
     {
       Console.WriteLine("嗨!我是客户端C...!");//B处
     }
    }//
    请注意上面A处,与B处,它是事件所真正调用的方法,它们是不同的,同一个事件不同的方法
      

  6.   

    上面有个地方写错改一下:
    我认为事件主要是一种面向对象思想的体现, class A{ 
    B b; 

    class B{ 
    A a; 
    } 双向引用的情况下,双方的公共方法全部暴露给对方,似乎弥补了只有通过事件来完成在单向引用时所提供的功能,但是 这可能仍然无法体现事件是独特作用... class A{ 
    public event Action <A> Teste; 
    protected virtual void OnTeste() 

      if(this.Teste!=null)this.Teste(this); 

    int data; 
    public int Data 

      get{return this.data;} 
      set{ 
        this.data=value; 
        if(data>10)this.OnTeste(); 
      } 


    //上面从设计的角度而言,这样写意味着,类A的开发者,仅需要确定一个方法的触发条件 
    而不关心方法的具体实现.这就是事件!这种设计是仅用普通方法所达不到的,在现实中我们
    可能会 遇到这样的设计情况,因此从面向对象的设计思想出发,事件的出现显得很自然,
    也很合理. 当把A给于不同的客户端时这种作用就会得以显现: 客户端B,和C class B{ 
      static void Main(){ 
        B b=new B(); 
      try{ 
        B.a.Data= Convert.ToInt32(Console.ReadLine());//事件的触发处 
      } 
      catch{} 

    A a; 
    a.Teste+=B_M1; 
    static void B_M1(A a) 

      Console.WriteLine("嗨!我是客户端B...!");//A处 


    //------------ 
    class C{ 
      static void Main(){ 
      C c=new C(); 
      try{ 
        C.a.Data= Convert.ToInt32(Console.ReadLine());//事件的触发处 
      } 
      catch{} 

    A a; 
    a.Teste+=C_M1; 
    static void C_M1(A a) 

      Console.WriteLine("嗨!我是客户端C...!");//B处 

    } // 
    请注意上面A处,与B处,它是事件所真正调用的方法,它们是不同的,同一个事件不同的方法.
      

  7.   

    人家Windows程序就是“事件”驱动型的
    虽然这两个含义可能不很一样
    但是从字眼上也能看出来还是又关系:
    没事件,程序跑不了,至少跑的不好看
    (纯属瞎扯)
      

  8.   

         针对给问题,我觉得3楼说得一针见血。      当2个类,事件处理方法所在的类(B)和事件定义所在的类(A)是两个平行的类,即互不包含时:
           A要调用B的方法有两个办法:
               1.通过事件实现。
               2.直接在A中产生B 的实例 b,再  b.想要的方法()即可。(但是这样就是一种紧耦合,不利代码重构。)
         
          但是当A是B类的一个成员变量时,如果再在A中实例化B可能造成一个死循环(构造时产生一个死循环).再这中情况下是要通过另外一个中间类将A的响应方法委托给B的!!~
      

  9.   


    笨,传A的引用进去给B不就OK了。