C # events
Event event
Definition: [Modifier] event void <delegate type> [interface type.] <event name>;
The event keyword is used to specify an event. Class and structure use events to notify objects of events that may affect the object status.
To add events to a class, you must use the event keyword and provide the delegate type and event name.
Events use delegates to provide type-safe encapsulation of called methods when triggered. The delegate can encapsulate the naming and anonymous methods.
In the following exampleTestButton
Contains the event onclick. Derived fromTestButton
Class can choose to respond to the onclick event and define the method to be called to process the event. You can specify multiple handlers in the form of Delegate and anonymous methods.
// Declare the handler delegate for the event
Public Delegate void buttoneventhandler ();
Class testbutton
{
// Onclick is an event, implemented by a delegate buttoneventhandler.
Public event buttoneventhandler onclick;
// A method that triggers the event:
Public void click ()
{
Onclick ();
}
} // Create an instance of the testbutton class.
Testbutton MB = new testbutton ();
// Specify the method that will be triggered by the onclick event.
MB. onclick + = new buttoneventhandler (testhandler );
// Specify an additional anonymous method.
MB. onclick + = delegate {system. Console. writeline ("Hello, world! ");};
// Trigger the event
MB. Click (); event Overview
Events have the following features:
An event is a method used to notify objects of certain operations.
Although events are useful at other times (such as changing the Signal status), they are usually used in graphical user interfaces.
Events are usually declared using a delegated event handler.
The event can be replaced by an anonymous method. For more information, see the anonymous method
Events
To trigger an event, the class can call the delegate and pass all event-related parameters. Then, the delegate calls all the handlers that have been added to the event. If the event does not have any handler, the event is empty. Therefore, before an event is triggered, the event source should ensure that the event is not empty to avoidNullReferenceException
. To avoid contention conditions (the last handler will be removed between the empty check and event call), before executing the empty check and triggering the event, the event source should also create a copy of the event. For example:
private void RaiseTestEvent(){ // Safely invoke an event: TestEventDelegate temp = TestEvent; if (temp != null) { temp(this, new System.EventArgs()); }}
Subscribe to events
Classes that want to receive an event can create a method to receive the event, and then add a delegate for the method to the class event itself. This process is called "subscription event ".
First, the receiving class must have the same signature (such as the delegate signature) as the event itself. Then, this method (called an event handler) can take appropriate actions to respond to the event. For example
public class EventReceiver{ public void ReceiveTestEvent(object sender, System.EventArgs e) { System.Console.Write("Event received from "); System.Console.WriteLine(sender.ToString()); }}
Each event can have multiple handlers. Multiple handlers are called by the source in order. If a handler causes an exception, a handler that has not yet been called has no chance to receive the event. For this reason, it is recommended that the event handler process the event quickly and avoid exceptions.
To subscribe to an event, the receiver must create a delegate of the same type as the event and use the event handler as the delegate target. Then, the receiver must use the addition assignment operator (+ =) Add the delegate to the event of the source object. For example:
public void Subscribe(EventSource source){ TestEventDelegate temp = new TestEventDelegate(ReceiveTestEvent); source.TestEvent += temp;}
To cancel the subscription, the receiver can use the subtraction assignment operator (-=) Removes the event handler delegate from the event of the source object. For example:
public void UnSubscribe(EventSource source){ TestEventDelegate temp = new TestEventDelegate(ReceiveTestEvent); source.TestEvent -= temp;}
Declare event accessors
Use the Add keyword and code block to add the event handler, and use the remove keyword and code block to remove the event handler.
public class EventSource2{ private TestEventDelegate TestEventHandlers; public event TestEventDelegate TestEvent { add { lock (TestEventHandlers) { TestEventHandlers += value; } } remove { lock (TestEventHandlers) { TestEventHandlers -= value; } } } private void RaiseTestEvent() { // Safely invoke an event. TestEventDelegate temp = TestEventHandlers; if (temp != null) { temp(this, new System.EventArgs()); } }}
In the preceding exampleLockStatement to prevent multiple threads from simultaneously operating the event list. See lock statements and thread processing.
Create Event Response controls
Case: a word processor may contain a list of opened documents. When this list is changed, you may need to notify many different objects in the word processor to update the user interface. When using the event, the code for maintaining the document list does not need to know who to notify. Once the document list is changed, the event will be automatically called to correctly notify every object to be notified. Using events improves program modularization.
MS-help: // Ms. VSCC. v80/ms. msdn. v80/ms. visualstudio. v80.chs/dv_csref/html/2d20556a-0aad-46fc-845e-f85d86ea617a.htm
Example:
namespace TestCollections{ // A delegate type for hooking up change notifications. public delegate void ChangedEventHandler(object sender, System.EventArgs e); // A class that works just like ArrayList, but sends event // notifications whenever the list changes. public class ListWithChangedEvent : System.Collections.ArrayList { // An event that clients can use to be notified whenever the // elements of the list change. public event ChangedEventHandler Changed; // Invoke the Changed event; called whenever list changes protected virtual void OnChanged(System.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(System.EventArgs.Empty); return i; } public override void Clear() { base.Clear(); OnChanged(System.EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(System.EventArgs.Empty); } } }}namespace TestEvents{ using TestCollections; class EventListener { private ListWithChangedEvent m_list; public EventListener(ListWithChangedEvent list) { m_list = list; // Add "ListChanged" to the Changed event on m_list: m_list.Changed += new ChangedEventHandler(ListChanged); } // This will be called whenever the list changes. private void ListChanged(object sender, System.EventArgs e) { System.Console.WriteLine("This is called when the event fires."); } public void Detach() { // Detach the event and delete the list m_list.Changed -= new ChangedEventHandler(ListChanged); m_list = null; } } class Test { // 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(); } }}
. NET framework guide indicates that the delegate type used for the event should use two parameters: "Object source" parameter (used to indicate the event source) event-specific parameters (it encapsulates any other information about the event ). Event-specific parameters should be derived from the eventargs class. For events that do not use any additional information,. NET Framework provides the eventhandler class.
As in the above example, modify the rule to. NET Framework.
namespace TestCollections{ // A class that works just like ArrayList, but sends event // notifications whenever the list changes: public class ListWithChangedEvent : System.Collections.ArrayList { // An event that clients can use to be notified whenever the // elements of the list change: public event System.EventHandler Changed; // Invoke the Changed event; called whenever list changes: protected virtual void OnChanged(System.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(System.EventArgs.Empty); return i; } public override void Clear() { base.Clear(); OnChanged(System.EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(System.EventArgs.Empty); } } }}
Declare an event in the interface, and then implement the event in the class
public delegate void TestDelegate(); // delegate declarationpublic interface ITestInterface{ event TestDelegate TestEvent; void FireAway();}public class TestClass : ITestInterface{ public event TestDelegate TestEvent; public void FireAway() { if (TestEvent != null) { TestEvent(); } }}public class MainClass{ static private void F() { System.Console.WriteLine("This is called when the event fires."); } static void Main() { ITestInterface i = new TestClass(); i.TestEvent += new TestDelegate(F); i.FireAway(); }}
Implement two interfaces with events with the same name
When you want to implement two interfaces with events of the same name, you also need to use the event attribute. In this case, you must use an explicit implementationEvent attributes.
However, when explicitly implementing events in an interface, you need to provide the add and remove methods.