An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object. The most familiar use for events is in graphical user interfaces; typically, the classes that represent controls in the interface have events that are notified when the user does something to the control (for example, click a button).
Events, however, need not be used only for graphical interfaces. Events provide a generally useful way for objects to signal state changes that may be useful to clients of that object. Events are an important building block for creating classes that can be reused in a large number of different programs.
Events are declared using delegates. If you have not yet studied the Delegates Tutorial, you should do so before continuing. Recall that a delegate object encapsulates a method so that it can be called anonymously. An event is a way for a class to allow clients to give it delegates to methods that should be called when the event occurs. When the event occurs, the delegate(s) given to it by its clients are invoked.
In addition to the examples on declaring, invoking, and hooking up to events, this tutorial also introduces the following topics:
The following simple example shows a class,
ListWithChangedEvent
, which is similar to the standard
ArrayList
class, but also invokes a Changed
event whenever the contents of the list change. Such a general-purpose class could be used in numerous ways in a large program.
For example, a word processor might maintain a list of the open documents. Whenever this list changes, many different objects in the word processor might need to be notified so that the user interface could be updated. By using events, the code that maintains the list of documents doesn‘t need to know who needs to be notified — once the list of documents is changed, the event is automatically invoked and every object that needs to be notified is correctly notified. By using events, the modularity of the program is increased.
// Events Tutorial - Chimomo using System; using System.Collections; namespace EventsTutorial { // A delegate type for hooking up change notifications. public delegate void ChangedEventHandler(object sender, EventArgs e); // A class that works just like ArrayList, but sends event notifications whenever the list changes. class ListWithChangedEvent : ArrayList { // An event that clients can use to be notified whenever the elements of list change. public event ChangedEventHandler Changed; // Invoke the Changed event; called whenever list changes. private void OnChanged(EventArgs e) { if (Changed != null) { Changed(this, e); } } // Override some of the methods that can change the list; invoke event after each. public override int Add(object value) { int i = base.Add(value); OnChanged(EventArgs.Empty); return i; } public override void Clear() { base.Clear(); OnChanged(EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(EventArgs.Empty); } } } }
// Events Tutorial - Chimomo using System; namespace EventsTutorial { class EventListener { private ListWithChangedEvent listWithChangedEvent; public EventListener(ListWithChangedEvent list) { listWithChangedEvent = list; // Add "ListChanged" to the Changed event on "listWithChangedEvent". listWithChangedEvent.Changed += ListChanged; } // This will be called whenever the list changes. private void ListChanged(object sender, EventArgs e) { Console.WriteLine("This is called when the event fires."); } public void Detach() { // Detach the event and delete the listWithChangedEvent. listWithChangedEvent.Changed -= ListChanged; listWithChangedEvent = null; } } }
// Events Tutorial - Chimomo namespace EventsTutorial { static class Program { // Test the ListWithChangedEvent class. static void Main() { // Create a new list. ListWithChangedEvent list = new ListWithChangedEvent(); // Create a class that listens to the list's change event. EventListener listener = new EventListener(list); // Add and remove items from the list. list.Add("Item 1"); list.Clear(); listener.Detach(); } } } // Output: /* This is called when the event fires. This is called when the event fires. */
public delegate void ChangedEventHandler(object sender, EventArgs e);The delegate type defines the set of arguments that are passed to the method that handles the event. Multiple events can share the same delegate type, so this step is only necessary if no suitable delegate type has already been declared.
Next, the event itself is declared.
public event ChangedEventHandler Changed;An event is declared like a field of delegate type, except that the keywordevent precedes the event declaration, following the modifiers. Events usually are declared public, but any accessibility modifier is allowed.
if (Changed != null) { Changed(this, e); }Invoking an event can only be done from within the class that declared the event.
- Compose a new delegate onto that field.
- Remove a delegate from a (possibly composite) field.
This is done with the += and-= operators. To begin receiving event invocations, client code first creates a delegate of the event type that refers to the method that should be invoked from the event. Then it composes that delegate onto any other delegates that the event might be connected to using+=.
// Add "ListChanged" to the Changed event on "listWithChangedEvent1". listWithChangedEvent1.Changed += ListChanged;When the client code is done receiving event invocations, it removes its delegate from the event by using operator-=.
// Detach the event and delete the listWithChangedEvent1. listWithChangedEvent1.Changed -= ListChanged;
When creating a general component that can be derived from, what seems to be a problem sometimes arises with events. Since events can only be invoked from within the class that declared them, derived classes cannot directly invoke events declared within the base class. Although this is sometimes what is desired, often it is appropriate to give the derived class the freedom to invoke the event. This is typically done by creating a protected invoking method for the event. By calling this invoking method, derived classes can invoke the event. For even more flexibility, the invoking method is often declared as virtual, which allows the derived class to override it. This allows the derived class to intercept the events that the base class is invoking, possibly doing its own processing of them.
In the preceding example, this has been done with the
OnChanged
method. A derived class could call or override this method if it needed to.
One other difference between events and fields is that an event can be placed in an interface while a field cannot. When implementing the interface, the implementing class must supply a corresponding event in the class that implements the interface.
Although the C# language allows events to use any delegate type, the .NET Framework has some stricter guidelines on the delegate types that should be used for events. If you intend for your component to be used with the .NET Framework, you probably will want to follow these guidelines.
The .NET Framework guidelines indicate that the delegate type used for an event should take two parameters, an "object source" parameter indicating the source of the event, and an "e" parameter that encapsulates any additional
information about the event. The type of the "e" parameter should derive from the
EventArgs class. For events that do not use any additional information, the .NET Framework has already defined an appropriate delegate type:
EventHandler.
原文地址:http://blog.csdn.net/troubleshooter/article/details/44455001