事件与委托--这篇文章算是讲的浅显明白
2004-08-24 09:48
232 查看
Download source files - 6.86 Kb Download demo project - 3.75 Kb IntroductionWhen I was trying to learn events and delegates, I read a lot of articles to completely understand what they are and how to use them, and now I want to present them all here, everything I learned, most of the things you need to learn.What are delegates?Delegate and Event concepts are completely tied together. Delegates are just function pointers, That is, they hold references to functions.A Delegateis a class. When you create an instance of it, you pass in the function name (as a parameter for delegate's constructor) to which this delegate will refer. Every delegate has a signature. For example: Delegate int SomeDelegate(string s, bool b); is a delegate declaration. When I say this delegate has a signature, I mean that it returns an inttype and takes 2 parameters of type stringand bool. I said, when you instantiate delegates, you pass in the function name to which this delegate will refer as its constructor parameter. The important thing to notice is that only functions that have the same signature as the delegate, can be passed as a parameter. Consider the following function: private int SomeFunction(string str, bool bln){...} You can pass this function to SomeDelegate's constructor, because of their similar signatures. SomeDelegate sd= new SomeDelegate(SomeFunction); Now, sdrefers to SomeFunction, in other words, SomeFunctionis registered to sd. If you call sd, SomeFunctionwill be invoked. Keep in mind what I mean by registered functions. Later, we will refer to registered functions. sd("somestring", true); Now that you know how to use delegates, let's understand events... Understanding EventsAButtonis a class, when you click on it, the clickevent fires. A Timeris a class, every millisecond a tickevent fires. Want to understand what's happening? Let's learn through an example: This is the scenario: we have a class named Counter. This class has a method named CountTo(int countTo, int reachableNum)which starts counting from 0 to countTo, and raises an event named NumberReachedwhenever it reaches the reachableNum. Our class has an event: NumberReached. Events are variables of type delegates. I mean, if you want to declare an event, you just declare a variable of type some delegate and put eventkeyword before your declaration like this: public event NumberReachedEventHandler NumberReached; In the above declaration, NumberReachedEventHandleris just a delegate. Maybe it was better to say: NumberReachedDelegate, but notice that Microsoft doesn't say MouseDelegateor PaintDelegate, instead it offers: MouseEventHandlerand PaintEventHandler. It's a convention to say NumberReachedEventHandlerinstead of NumberReachedDelegate. OK? Good! You see, before we declare our event, we need to define our delegate (our event handler). It could be something like this: public delegate void NumberReachedEventHandler(object sender, NumberReachedEventArgs e); As you see, our delegate's name is: NumberReachedEventHandler, and its signature contains a voidreturn value and 2 parameters of type objectand NumberReachedEventArgs. If you somewhere want to instantiate this delegate, the function passed in as constructor parameter should have the same signature as this delegate. Have you ever used PaintEventArgsor MouseEventArgsin your code to determine the position of mouse, where it was moving, or the Graphicsproperty of the object which raised the Paintevent? Actually, we provide our data for the user in a class which is derived from EventArgsclass. For example, in our example, we want to provide the number which was reached. And here is the class definition: public class NumberReachedEventArgs : EventArgs If it wouldn't be necessary to provide the user with any information, we just use the EventArgsclass. Now, every thing is prepared to take a look inside our Counterclass: namespace Events if(ctr == reachableNum) Good question! If you want to know why we called indirectly, take another look at OnNumberReached's signature: protected virtual void OnNumberReached(NumberReachedEventArgs e) You see, this method is protected, it means it's available for classes which are derived from this class (inheriting classes). This method is also virtual, this means that it could be overridden in a derived class. And this is very useful. Suppose you are designing a class which inherits from Counterclass. By overriding OnNumberReachedmethod, you can do some additional work in your class before the event gets raised. An example: protected override void OnNumberReached(NumberReachedEventArgs e) Note that if you don't call base.OnNumberReached(e), the event will never be raised! This might be useful when you are inheriting from some class and want to eliminate some of its events! An interesting trick, huh? As a real world example, you can just create a new ASP.NET Web Application and take a look inside the code behind generated. As you see, your page inherits from System.Web.UI.Pageclass. This class has a virtualand protectedmethod name OnInit. You see that InitializeComponent()method is called inside the overridden method as an extra work, and then OnInit(e)is called in the base class: Notice that NumberReachedEventHandlerdelegate is defined outside our class, inside the namespace, visible to all classes. OK. Now, it's time to practically use our Counterclass: In our sample application, we have 2 textboxes named txtCountToand txtReachableas follows: private void cmdRun_Click(object sender, System.EventArgs e) private void oCounter_NumberReached(object sender, NumberReachedEventArgs e) oCounter.NumberReached += new NumberReachedEventHandler( oCounter_NumberReached); oCounter.NumberReached += new NumberReachedEventHandler( oCounter_NumberReached2);[/code] Now, after raising an event, both functions will be invoked one after another. If somewhere in your code, based on conditions, you decided oCounter_NumberReached2not be invoked anymore on NumberReachedevent occurrences, you could simply do this: oCounter.NumberReached -= new NumberReachedEventHandler( oCounter_NumberReached2); FinallyDon't forget to define these lines in your application's main constructor, instead ofcmdRun_Clickevent handler. I defined them in my button click event handler just for the sake of simplicity! ;-) public Form1() // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // oCounter= new Counter(); oCounter.NumberReached += new NumberReachedEventHandler( oCounter_NumberReached); oCounter.NumberReached += new NumberReachedEventHandler( oCounter_NumberReached2); The source code provided by this article is as above. If your vote is less than 5, let me know the reason ;-). I hope you will be satisfied after reading this article! |
相关文章推荐
- 理解委托和事件的好文章http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html
- C#委托及事件委托的初步理解(经典文章)
- 封装、继承、多态、接口、枚举、委托、多线程、集合、事件、都明白了?
- 关于委托的一篇不错的文章(C# 中的委托和事件)
- 个人关于委托事件的一些浅显认识
- 细读文章:C#中的委托和事件
- 委托与事件——系列文章收藏
- 【MS】关于委托、事件、泛型文章整理
- 理解委托与事件的好文章
- 一篇讲述委托和事件的好文章
- 很好的一篇关于C#事件与委托的文章
- c# 委托事件 看到的几篇好文章
- 对张子阳先生对委托和事件的两篇文章的读后思考(说得很透,内附故事一篇)
- 【转】理解委托与事件的好文章
- 两篇关于委托和事件的文章之一
- C#中的委托和事件文章收藏
- 两篇关于委托和事件的文章之二___详解C#委托,事件与回调函数
- .NET委托与事件文章收集
- 最简单最明白的关于“事件”和“委托”的例子说明
- 浅显易懂的事件和委托