c# 委托和事件

来源:互联网 发布:ape进销存电商erp源码 编辑:程序博客网 时间:2024/06/07 05:39

  事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂。而这些东西却往往又是编程中常用且非常重要的东西。大家都知道windows消息处理机制的重要,其实C#事件就是基于windows消息处理机制的,只是封装的更好,让开发者无须知道底层的消息处理机制,就可以开发出强大的基于事件的应用程序来。

先来看看事件编程有哪些好处。
在以往我们编写这类程序中,往往采用等待机制,为了等待某件事情的发生,需要不断地检测某些判断变量,而引入事件编程后,大大简化了这种过程:
- 使用事件,可以很方便地确定程序执行顺序。
- 当事件驱动程序等待事件时,它不占用很多资源。事件驱动程序与过程式程序最大的不同就在于,程序不再不停地检查输入设备,而是呆着不动,等待消息的到来,每个输入的消息会被排进队列,等待程序处理它。如果没有消息在等待,则程序会把控制交回给操作系统,以运行其他程序。
- 事件简化了编程。操作系统只是简单地将消息传送给对象,由对象的事件驱动程序确定事件的处理方法。操作系统不必知道程序的内部工作机制,只是需要知道如何与对象进行对话,也就是如何传递消息。

  有了这么多好处,看来我们的确有必要掌握它。俗话说:“难了不会,会了不难”。就让我们一步一步开始吧...

  要讲事件,必然要讲到委托(delegate)。它们之间的关系可以通过一个浅显的比方来说明,这个比方可能不是十分恰当。比如你要租一个房屋,这是一个事件,那么委托就是房屋租赁中介,当你把租房子的消息告知中介后,中介就会产生出一套符合你要求的房屋租赁方案来。再由中介执行这套方案,你便租得了这个房屋,即事件被处理了。当然你也可以不通过中介,直接找房东,但如果没有互联网等工具,你如何得到谁出租房屋的信息?话题扯远了。

委托(delegate)
委托可以理解成为函数指针,不同的是委托是面向对象,而且是类型安全的。关于委托的理解,可以参考我的另一篇文章《C#委托之个人理解》。

事件(event)
  我们可以把事件编程简单地分成两个部分:事件发生的类(书面上叫事件发生器)和事件接收处理的类。事件发生的类就是说在这个类中触发了一个事件,但这个类并不知道哪个个对象或方法将会加收到并处理它触发的事件。所需要的是在发送方和接收方之间存在一个媒介。这个媒介在.NET Framework中就是委托(delegate)。在事件接收处理的类中,我们需要有一个处理事件的方法。好了,我们就按照这个顺序来实现一个捕获键盘按键的程序,来一步一步说明如何编写事件应用程序。

1、首先创建一个自己的EventArgs类。
引自MSDN:
EventArgs是包含事件数据的类的基类,此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。

因为在我们键盘按键事件中要包含按键信息,所以要派生一个KeyEventArgs类,来保存按键信息,好让后面知道按了哪个键。

internal class KeyEventArgs : EventArgs
{
    
private char keyChar;
    
public KeyEventArgs( char keyChar ) : base()
    
{
        
this.keyChar = keyChar;
    }


    
public char KeyChar
    
{
        
get
        
{
            
return keyChar;
        }

    }

}


2、再创建一个事件发生的类KeyInputMonitor,这个类用于监控键盘按键的输入并触发一个事件:

internal class KeyInputMonitor
{
    
// 创建一个委托,返回类型为void,两个参数
    public delegate void KeyDownHandler( object sender, KeyEventArgs e );
    
// 将创建的委托和特定事件关联,在这里特定的事件为KeyDown
    public event KeyDownHandler KeyDown;

    
public void Run()
    
{
        
bool finished = false;
        
do
        
{
            Console.WriteLine( 
"Input a char" );
            
string response = Console.ReadLine();

            
char responseChar = ( response == "" ) ? ' ' : char.ToUpper( response[0] );
            
switch( responseChar )
            
{
                
case 'X':
                    finished 
= true;
                    
break;
                
default:
                    
// 得到按键信息的参数
                    KeyEventArgs keyEventArgs = new KeyEventArgs( responseChar );
                    
// 触发事件
                    KeyDown( this, keyEventArgs );
                    
break;
            }

        }
while!finished );
    }

}


这里注意KeyDown( this, KeyEventArgs );一句,这就是触发事件的语句,并将事件交由
KeyDownHandler这个委托来处理,委托指定事件处理方法去处理事件,这就是事件接收方的类的事情了。参数this是指触发事件的对象就是本身这个对象,keyEventArgs包含了按键信息。

3、最后创建一个事件接收方的类,这个类先产生一个委托实例,再把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件。然后提供一个方法回显按键信息。

internal class EventReceiver
{
    
public EventReceiver( KeyInputMonitor monitor )
    
{
        
// 产生一个委托实例并添加到KeyInputMonitor产生的事件列表中
        monitor.KeyDown += new KeyInputMonitor.KeyDownHandler( this.OnKeyDown );
    }

    
private void OnKeyDown(object sender, KeyEventArgs e)
    
{
        
// 真正的事件处理函数
        Console.WriteLine( "Capture key: {0}", e.KeyChar );
    }

}


4、看一下如何调用

public class MainEntryPoint
{
    
public static void Start()
    
{
        
// 实例化一个事件发送器
        KeyInputMonitor monitor = new KeyInputMonitor();
        
// 实例化一个事件接收器
        EventReceiver eventReceiver = new EventReceiver( monitor );
        
// 运行
        monitor.Run();
    }

}


总结:

C#中使用事件需要的步骤:
1.创建一个委托
2.将创建的委托与特定事件关联(.Net类库中的很多事件都是已经定制好的,所以他们也就有相应的一个委托,在编写关联事件处理程序--也就是当有事件发生时我们要执行的方法的时候我们需要和这个委托有相同的签名)
3.编写事件处理程序
4.利用编写的事件处理程序生成一个委托实例
5.把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件

C#中事件产生和实现的流程:
1.定义A为产生事件的实例,a为A产生的一个事件
2.定义B为接收事件的实例,b为处理事件的方法
3.A由于用户(程序编写者或程序使用者)或者系统产生一个a事件(例如点击一个Button,产生一个Click事件)
4.A通过事件列表中的委托对象将这个事件通知给B
5.B接到一个事件通知(实际是B.b利用委托来实现事件的接收)
6.调用B.b方法完成事件处理
    public class A
    {
        public delegate void EventHandler(object sender);
        public event EventHandler a;

        public void Run()
        {
            Console.WriteLine("Trigger an event.");
            a(this);
        }
    }

    class B
    {
        public B(A a)
        {
            a.a += new A.EventHandler(this.b);
        }
        private void b(object sender)
        {
            Console.WriteLine("Received and handled an event." );
            Console.Read();
        }
    }
不当之处,欢迎指正。
(完)

好文要顶 关注我 收藏该文  
loose_went
关注 - 1
粉丝 - 218
+加关注
26
0
(请您对文章做出评价)
« 上一篇:虚方法(virtual)和抽象方法(abstract)的区别
» 下一篇:『C程序设计』读书笔记系列文章之第一章 概述
posted @ 2008-04-02 11:19 loose_went 阅读(78293) 评论(48) 编辑 收藏

  
#1楼 2008-04-02 12:16 shen126[未注册用户]
个人认为,在.Net下,delegate和event似乎没有本质的区别。 
之所以需要加入event类型,是因为如果只有server端只有delegate的话,那么client端同样可以调用server.delegate来触发事件。另外,event可以定制其添加删除权限。 
不知道理解是否正确? 
  
#2楼 2008-04-02 12:23 李战  
拜读,谢谢!
支持(0)反对(0)
  
#3楼[楼主2008-04-02 12:31 loose_went  
@shen126 
我觉得事件应该是委托的一个特殊实例,其实委托还可以做很多事。
支持(0)反对(0)
  
#4楼[楼主2008-04-02 12:39 loose_went  
这有一个很好的例子,有助于理解事件机制。 

using System; 

namespace Vczx.ProCSharp.Event 

/// <summary> 
/// 类EatEventArgs 必须继承自类EventArgs,用来引发事件时封装数据 
/// </summary> 
public class EatEventArgs : EventArgs 

public String restrauntName; //饭店名称 
public decimal moneyOut; //准备消费金额 


/// <summary> 
/// 这个委托用来说明处理吃饭事件的方法的方法头(模式) 
/// </summary> 
public delegate void EatEventHandler(object sender, EatEventArgs e); 

/// <summary> 
/// 引发吃饭事件(EateEvent)的类Master(主人),这个类必须 
/// 1.声明一个名为EatEvent的事件: public event EatEventHandler EatEvent; 
/// 2.通过一个名为OnEatEvent的方法来引发吃饭事件,给那些处理此事件的方法传数据; 
/// 3.说明在某种情形下引发事件呢?在饿的时候。用方法Hungrg来模拟。 
/// </summary> 
public class Master 

//声明事件 
public event EatEventHandler EatEvent; 

//引发事件的方法 
public void OnEatEvent(EatEventArgs e) 

if (EatEvent != null) 

EatEvent(this, e); 



//当主人饿的时候,他会指定吃饭地点和消费金额。 
public void Hungry(String restrauntName, decimal moneyOut) 

EatEventArgs e = new EatEventArgs(); 
e.restrauntName = restrauntName; 
e.moneyOut = moneyOut; 

Console.WriteLine("主人说:"); 
Console.WriteLine("我饿了,要去{0}吃饭,消费{1}元", e.restrauntName, e.moneyOut); 

//引发事件 
OnEatEvent(e); 



/// <summary> 
/// 类Servant(仆人)有一个方法ArrangeFood(安排食物)来处理主人的吃饭事件 
/// </summary> 
public class Servant 

public void ArrangeFood(object sender, EatEventArgs e) 

Console.WriteLine(); 
Console.WriteLine("仆人说:"); 
Console.WriteLine("我的主人, 您的命令是 : "); 
Console.WriteLine("吃饭地点 -- {0}", e.restrauntName); 
Console.WriteLine("准备消费 -- {0}元 ", e.moneyOut); 
Console.WriteLine("好的,正给您安排。。。。。。。。\n"); 
System.Threading.Thread.Sleep( 5000 ); 
Console.WriteLine("主人,您的食物在这儿,请慢用"); 
Console.Read(); 



/// <summary> 
/// 类God安排qinshihuang(秦始皇)的仆人是lisi(李斯),并让李斯的ArrangeFood 
/// 方法来处理qinshihuang的吃饭事件:qinshihuang.EatEvent += new EatEventHandler(lishi.ArrangeFood); 
/// </summary> 
public class God 

public static void Start() 

Master qinshihuang = new Master(); 
Servant lishi = new Servant(); 

qinshihuang.EatEvent += new EatEventHandler(lishi.ArrangeFood); 

//秦始皇饿了,想去希尔顿大酒店,消费5000元 
qinshihuang.Hungry("希尔顿大酒店", 5000.0m); 




输出: 

主人说: 
我饿了,要去希尔顿大酒店吃饭,消费5000.0元 

仆人说: 
我的主人, 您的命令是 : 
吃饭地点 -- 希尔顿大酒店 
准备消费 -- 5000.0元 
好的,正给您安排。。。。。。。。 

主人,您的食物在这儿,请慢用
支持(4)反对(0)
  
#5楼 2008-04-02 13:06 deerchao  
大家都知道windows消息处理机制的重要,其实C#事件就是基于windows消息处理机制的. 
----------------- 
请问这段话有何依据? 
再请问C语言里的函数指针是否也是基于windows消息处理机制的?
支持(0)反对(3)
  
#6楼 2008-04-02 13:19 mickeysuda  
请问代码折叠的效果怎么做的?
支持(0)反对(0)
  
#7楼 2008-04-02 13:25 装配脑袋  
我面试时的时候喜欢问一道题:event和delegate类型的字段到底有什么区别。到目前为止,面试的人不多,但是没有一个答对的…… 

我记得我2003年面试一家.NET公司的时候,这是别人问我的一道面试题。我觉得这个还是相当基础的问题吧。。享受event便利的同时,是应该也思考一下背后的原理才对。
支持(2)反对(0)
  
#8楼 2008-04-02 14:20 xinqiyang  
看了楼主的好文章的了,收藏下的了呵呵......
支持(0)反对(0)
  
#9楼 2008-04-02 15:17 相思豆[未注册用户]
控件编程中的事件应该更好理解机制~
  
#10楼 2008-04-02 16:35 wit2[未注册用户]
OnKeyDown 一般做成方法,里面激发KeyDown事件 LZ看多微软的On··· 但哪个On···是事件呢
  
#11楼 2008-04-02 16:38 HelpForPersonal  
SHOUC
支持(0)反对(0)
  
#12楼 2008-04-02 17:31 shen126[未注册用户]
loose_went: 

@shen126 
我觉得事件应该是委托的一个特殊实例,其实委托还可以做很多事。 
--- 

同意,event就是一个伪装过的delegate,呵呵。
  
#13楼 2008-04-02 19:20 装配脑袋  
问题是event做了何种伪装,目的是什么,这一点最重要。但是面试中无一人知道:(
支持(0)反对(0)
  
#14楼 2008-04-02 21:42 yellowyu  
@装配脑袋

个人以为,事件的订阅者即是订阅了该委托的回调,而事件的发起,则是发送出消息,回调了订阅者注册时的函数

期待答案!!!!!
支持(0)反对(0)
  
#15楼 2008-04-02 22:12 kisskiki[未注册用户]
为了理解装配脑袋说得内容,特地搜索了下网上的文章,可惜大多数也只能讲到这篇文章提到的层面,稍微深入点的也就是idior的讨论delegate的文章和与其相关联的一篇文章 
不知道装配脑袋能否介绍几篇和你论述的“伪装”相关的文章了?非常想深刻理解它!苦于不得其法啊 

http://www.cnblogs.com/idior/articles/100666.html 
http://linkcd.cnblogs.com/archive/2005/07/19/196087.html 
http://idior.cnblogs.com/archive/2005/02/03/101510.aspx
  
#16楼 2008-04-03 09:51 装配脑袋  
实际上,event体现了封装性。event就是两个方法——add和remove组成的,当你写下button1.Click+=XXX的时候,其实就是使用了event的add方法。而-=就调用了remove方法。就和属性的get/set方法思想是一样。这样做的目的就是,事件从对象外部只能够增加新的响应方法,删除已知响应方法,而不能引发事件,或者获取其他人注册的响应方法等信息。而使用delegate共有字段则不能做出这些限制。
支持(2)反对(0)
  
#17楼 2008-04-03 10:00 装配脑袋  
当你写下这样的事件声明:
public event EventHandler Foo;

其实是生成了这样的代码:
private EventHandler FooEvent; //一个私有的委托字段,实现事件的内部机制
public event EventHandler Foo
{
    add
    {
        
//当用户用+=添加Foo事件的响应方法时,这个add过程将被调用
        FooEvent = Delegate.Combine(FooEvent, value);
    }
    remove
    {
        
//当用户用-=解除Foo事件的响应方法时,这个remove过程将被调用
        FooEvent = Delegate.Remove(FooEvent, value);
    }
}

支持(0)反对(0)
  
#18楼 2008-04-03 10:44 Microshaoft  
1.public delegate void FireEventHandler(string s); //委托 
2.public static event FireEventHandler FireStatic; //事件 
3.还有消费者的订阅后,自己实现的“时间处理函数” 

说:事件是“函数指针”个人觉得更恰当 
委托是“指针类型”? 



委托:相当于类型(可在接口(interface)中声明,体现的还是约定,强制实现类实现) 
事件:相当于类型的实例,实现 
当然“委托”能够起到“接口”的约束作用 

有“多态”的作用, 
重点要考察“事件的提供者”的知识点 
事件的提供者:实现在恰当逻辑下发出事件,callback 给消费者先前订阅的处理函数 DelegateInstance(eventargs),“DelegateInstance≈event” 
event 不是 类型只是一个关键字 
事件的消费者: 

复习一下 .Net: delegate(委托)、event(事件) 的基础知识,从头到尾实现事件! 
http://www.cnblogs.com/Microshaoft/archive/2005/05/30/164753.html
支持(0)反对(0)
  
#19楼 2008-04-03 13:22 kisskiki[未注册用户]
谢谢装配脑袋的指点,我明白了,不过还得多思考下。 
谢谢Microshaoft的指点,你的这篇文章很早就拜读过,不过当时对于这样一些基本概念没着重去理解,现在一定好好理解。
  
#20楼 2008-04-03 19:22 henry  
其实有什么比MSDN更详细: 
事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处理程序方法。 

委托具有以下特点: 
委托类似于 C++ 函数指针,但它们是类型安全的。 
委托允许将方法作为参数进行传递。 
委托可用于定义回调方法。 
委托可以链接在一起;例如,可以对一个事件调用多个方法。 


事件具有以下特点: 
发行者确定何时引发事件,订户确定执行何种操作来响应该事件。 
一个事件可以有多个订户。一个订户可处理来自多个发行者的多个事件。 
没有订户的事件永远不会被调用。 
事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。 
如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。 
可以利用事件同步线程。 
支持(0)反对(0)
  
#21楼 2008-04-06 21:41 MS的明天  
好文,谢谢
支持(0)反对(0)
  
#22楼 2008-04-09 10:52 房客  
刚刚我看了以上各位的留言回复,我说一下自己的看法,可能和装配脑袋的看法有些出入:

首先,event和委托的区别不在于是谁封装了谁,而是它们两者之间就根本没有可比性。
event是一个修饰符,delegate是一个类。就好像static修饰符和String类型,它们有什么可比性?

声明一个事件的时候,
public event delegate eventname;
只是告诉声明这个委托是以事件的形式声明的。
以event修饰符声明一个委托之后,该委托变量就可以使用+=或者-=重载运算符了。
比如,不使用event来实现的类似于事件的方法:
using System;
using System.Collections.Generic;
using System.Text;

namespace PrintTemplate
{
    
public delegate void DelSample(object sender,EventArgs e);

    
public class Test
    
{
        
public DelSample eventsample;
        
public void Run()
        
{
            eventsample.Invoke(
thisnew EventArgs());
        }

    }


    
public class Voke
    
{
        
public Voke()
        
{
            Test test 
= new Test();
            test.eventsample 
= OnClick;
            test.Run();
        }

        
public void OnClick(object sender,EventArgs e)
        
{
            
        }

    }

}

注意的是,上面这个例子,并没有使用event修饰符,同样达到了使用修饰符event的效果。(或者说是使用修饰符event达到了上面的效果更恰当一些吧。)
调用时,test.eventsample是作为一个test对象的一个公共变量来对其赋值的。只有对其符了值,在test.Run()时,才可以正确的调用该委托的方法。这个是完全符合我们平时编码习惯的。不少人搞不清event的机制原理看了这个应该就明白了。

而使用event修饰符来完成这个操作的代码:
using System;
using System.Collections.Generic;
using System.Text;

namespace PrintTemplate
{
    
public delegate void DelSample(object sender,EventArgs e);

    
public class Test
    
{
        
public event DelSample eventsample;
        
public void Run()
        
{
            eventsample.Invoke(
thisnew EventArgs());
        }

    }


    
public class Voke
    
{
        
public Voke()
        
{
            Test test 
= new Test();
            test.eventsample 
+= new DelSample(OnClick);
            test.Run();
        }

        
public void OnClick(object sender,EventArgs e)
        
{
            
        }

    }

}

从这个例子不难看出,和上面未使用event的例子,完成的作用完全是一模一样的。但是MS肯定不会平白无故的就添这么一个东西出来。就我目前来看,应该是为了更好的多绑定委托才实现的。上面装配脑袋所说的Delegate.combin(delegate,delegate)和Delegate.Remove(...),同样也可以完全取代event完成的这个效果,但显然不如使用event修饰符来的直观一些。

所以说,event是为了方便delegate才由MS弄出来这么一个东西,它是为后者服务的,有了它,你可以更加方便的使用委托,提高你的工作效率。
至于修饰符到底是什么东西,什么工作机制,恕我直言,我现在还真没有搞清楚,可能它是为编译器工作的,在编译的时候,根据某种规则编码机器语言的吧。这个你可以不相信我。

现在在上班,没时间写的很详细,大概讲一下。有什么问题,可以回复或者去我的blog里面给我留言,大家一起讨论。

支持(2)反对(1)
  
#23楼 2008-04-09 15:20 Da Vinci  
为什么Run()在KeyInputMonitor中? 按你的说法似乎应该是 EventReceiver() 来处理Run()
支持(0)反对(0)
  
#24楼 2008-04-09 15:23 Da Vinci  
Sorry 我弄错了 你的说法是对的
支持(0)反对(0)
  
#25楼 2008-11-02 21:57 syz  
同意 房客 
event和delegate感觉就是没有可比性 
public event delegate delegate1 仅仅是对这个delegate1作了一个修饰而已,不用event同样可以实现,而用了前者这样在订阅的时候只能是+=或者-=的形式,至于为何这样,我想MS是为了安全的考虑?因为使客户订阅,那么delegate1必须是public,否则失去意义,而如果不使用event,体现不出事件的含义,并且客户端可以随意赋值
支持(0)反对(0)
  
#26楼 2008-12-17 15:37 iwuyudong  
谢谢楼主这么好的文章,看后受益匪浅。
支持(0)反对(0)
  
#27楼 2008-12-23 10:32 aryang[未注册用户]
非常感谢,作者写的很好,我总算对事件委托有了一个比较清楚的认识。
  
#28楼 2009-03-08 03:24 arlang[未注册用户]
个人认为Event和delegate ,delegate是定义,而 event是声明一个类型为delegate 所指的那个类型的对象,也许还没实例化。另,即使只用 delegate仍可以使用+=和-=。
  
#29楼 2009-10-12 20:19 imnath!  
感谢楼主 现在急需关于时间处理的知识 这篇文章无异于雪中送炭
支持(0)反对(0)
  
#30楼[楼主2009-10-19 10:23 loose_went  
大家共同学习,乐于分享,营造一个好的学习氛围,希望天天进步。
支持(0)反对(0)
  
#31楼 2010-09-28 15:05 logxing  
感觉很多人的理解还是不正确。楼主的例子中的事件句柄名和事件名也容易让人混淆。例如On前缀的一般不应该是事件名,而是基类的事件触发方法名。等等等等,应该再写一篇文章。
支持(0)反对(0)
  
#32楼[楼主2010-09-28 21:39 loose_went  
@logxing
你说的没错,关于这一点我已经修改了。
一般情况下,代理被定义为XxxHandler比较好,而Xxx则为事件名,处理这个事件的具体方法定义为OnXxx比较好,这样就容易理解一些了。
比如在本文中,代理定义为KeyDownHandler,意为这是专门处理KeyDown的代理;事件定义为KeyDown;而处理事件的方法定义为OnKeyDown。
虽然如何命名并不会影响程序的逻辑与性能,但一个好的命名会使程序的可读性、可维护性大大提高。
支持(0)反对(0)
  
#33楼 2010-10-04 12:17 logxing  
基类中的OnXXX其实是事件触发方法,虽然也可以在此写事件处理代码,但按照微软的原意,并不是要在此处理事件,在微软自己的Onxxx之类的方法的说明写的是触发事件,如OnPaint是触发Paint事件。
Onxxx标准的代码如下(引自一些微软的程序的反编译):
protected void OnExiting()   {        if (this.Exiting != null)        {            this.Exiting(this,EventArgs.Empty);        }    }

常规的添加事件处理一般是通过XXX += new XxxHandler(自定义事件处理方法,参数)。但是如果是在派生类中则可以重写OnXXX来添加事件处理代码,意味着“触发事件前或后(取决于新添的代码在base.Onxxx之前还是之后)伴随着要做这些处理”,这和“新添事件处理”有微妙的差异。这些代码只是逻辑上是事件处理,本身并不是事件委托的一部分。但还是应明确理解为“伴随着事件触发做的预处理或后处理”比较好,否则有时候容易引起混乱。
支持(0)反对(0)
  
#34楼[楼主2010-10-08 22:53 loose_went  
@logxing
嗯,这样理解也不错!但关键是要理解。。。
支持(0)反对(0)
  
#35楼 2011-01-28 18:57 shiragiku  
lz, 这个代码里把event这个关键字去掉了也能行。
咋回事啊?
欢迎邮件shiragiku@qq.com
支持(0)反对(0)
  
#36楼 2011-08-03 14:50 澍可  
第二段代码后的解说是什么啊?和代码都不对照,认真点啊
支持(0)反对(0)
  
#37楼 2011-08-04 09:16 bevan1982  
你好,看了一下解释受益匪浅。 有些地方理解的不是很好
KeyEventArgs keyEventArgs = new KeyEventArgs( responseChar );                    // 触发事件                    KeyDown( this, keyEventArgs );                    break;

是触发事件的,同时传入的是得到按键的参数,this 如何理解呢?

在实例化一个事件接收器时, 给委托添加的函数是 
  private void OnKeyDown(object sender, KeyEventArgs e)    {        // 真正的事件处理函数        Console.WriteLine( "Capture key: {0}", e.KeyChar );    }那么 sender 和 KeyEventArgs e 怎么理解? 请详细讲一下你的理解。 谢谢
支持(0)反对(0)
  
#38楼[楼主2011-08-04 17:02 loose_went  
@澍可
谢谢提醒,已经做了修改。
支持(0)反对(0)
  
#39楼[楼主2011-08-04 17:09 loose_went  
@bevan1982
this表示当前这个实例本身。 sender就是KeyDown事件触发时传过来的this,e是传过来的参数。
支持(0)反对(0)
  
#40楼 2011-12-23 11:21 gadfly[未注册用户]
学习了,真佩服!
  
#41楼 2012-05-26 23:10 初雪之恋  
文章很好,讨论的也很精彩,受益匪浅.谢谢
支持(0)反对(0)
  
#42楼 2012-06-29 10:40 NONONOON  
@deerchao
其实,WINDOWS的消息机制内部就是采用函数指针形式的,去看下消息映射宏和CmdTarget类吧!
支持(0)反对(0)
  
#43楼 2012-07-16 15:11 小桂子的博客  
@mickeysuda
#region 
#endregion
支持(0)反对(0)
  
#44楼 2012-07-16 16:36 小桂子的博客  
看了许多,即使理解了lz的讲解,很好,只是还是不大理解触发机制。我自己完全从0开始自定义一个控件,而不是从Control或者UserControl类编写一个控件,那么我们怎么定义事件的触发呢?比如我们按下鼠标或者敲入键盘等等。
QQ:892334612
谢谢...
支持(0)反对(0)
  
#45楼 2012-10-18 17:14 leowork  
学习了。
支持(0)反对(0)
  
#46楼 2013-06-17 15:27 西安用户  
@deerchao
引用大家都知道windows消息处理机制的重要,其实C#事件就是基于windows消息处理机制的.

-----------------

请问这段话有何依据?

再请问C语言里的函数指针是否也是基于windows消息处理机制的?

本末倒置
支持(0)反对(0)
  
#47楼 2013-10-15 20:02 King_Boxing  
@装配脑袋
event 禁用了+ -运算符,防止委托链被覆盖。只有包含这个委托的类才能发布消息。刚开始学c# 是不是这个意思呢
支持(0)反对(0)
  
#48楼 2015-05-14 16:13 一生飘摇  
拜读,想请大神来我们公司哈:)
B2B电商领头羊找钢网(D轮,10亿美金估值)发招贤榜,项目经理、产品、技术(.net、java、架构、Web前端、测试)速速加盟。入职即送最低10000股期权(回报预计百万以上)。截至5月30号。
工作地点:上海市杨浦区逸仙路25号 同济晶度大厦
有兴趣的私聊我,或者简历直接发我qq邮箱:22045514@qq.com。
也欢迎其他朋友前来。

0 0
原创粉丝点击