YouTip LogoYouTip

Csharp Event

# C# Event C# Event is a member that sends a specific event notification to subscribers. Events are commonly used to implement the observer pattern, which allows an object to notify other objects of state changes without needing to know the details of those objects. An **Event** is essentially a user action, such as a key press, click, mouse movement, etc., or some notification message, such as a system-generated alert. Applications need to respond to events when they occur. For example, an interrupt. The event mechanism in C# is used to implement communication between threads. **Key Points:** * **Declare a Delegate**: Define the delegate type that the event will use. A delegate is a function signature. * **Declare an Event**: Use the `event` keyword to declare an event. * **Raise the Event**: Call the event at the appropriate time to notify all subscribers. * **Subscribe and Unsubscribe from Events**: Other classes can subscribe to and unsubscribe from events using the `+=` and `-=` operators. ## Using Delegates with Events Events are declared and raised within a class and are associated with event handlers through delegates within the same class or other classes. The class containing the event is used to publish the event. This is known as the **publisher** class. Other classes that accept the event are known as **subscriber** classes. Events use the **publisher-subscriber** model. The **publisher** is an object that contains the event and delegate definitions. The connection between the event and delegate is also defined within this object. An object of the publisher class invokes this event and notifies other objects. The **subscriber** is an object that accepts the event and provides an event handler. The delegate in the publisher class invokes a method (the event handler) in the subscriber class. ## Declaring an Event To declare an event within a class, you must first declare the delegate type for the event. For example: public delegate void BoilerLogHandler(string status); Then, declare the event itself using the **event** keyword: // Define the event based on the above delegate public event BoilerLogHandler BoilerEventLog; The above code defines a delegate named _BoilerLogHandler_ and an event named _BoilerEventLog_, which invokes the delegate when raised. The following example demonstrates how to use events in C#: ## Example using System; namespace EventDemo { // Define a delegate type for the event handler public delegate void NotifyEventHandler(object sender, EventArgs e); // Publisher class public class ProcessBusinessLogic { // Declare the event public event NotifyEventHandler ProcessCompleted; // Method to raise the event protected virtual void OnProcessCompleted(EventArgs e) { ProcessCompleted?.Invoke(this, e); } // Simulate a business logic process and raise the event public void StartProcess() { Console.WriteLine("Process Started!"); // Here you can add actual business logic // Business logic completes, raise the event OnProcessCompleted(EventArgs.Empty); } } // Subscriber class public class EventSubscriber { public void Subscribe(ProcessBusinessLogic process) { process.ProcessCompleted += Process_ProcessCompleted; } private void Process_ProcessCompleted(object sender, EventArgs e) { Console.WriteLine("Process Completed!"); } } class Program { static void Main(string[] args) { ProcessBusinessLogic process = new ProcessBusinessLogic(); EventSubscriber subscriber = new EventSubscriber(); // Subscribe to the event subscriber.Subscribe(process); // Start the process process.StartProcess(); Console.ReadLine(); } } } ### Explanation 1. Define the delegate type: public delegate void NotifyEventHandler(object sender, EventArgs e); This is a delegate type that defines the signature for the event handler. Typically, `EventHandler` or `EventHandler` is used instead of a custom delegate. 2. Declare the event: public event NotifyEventHandler ProcessCompleted; This is an event using the NotifyEventHandler delegate type. 3. Raise the event: protected virtual void OnProcessCompleted(EventArgs e){ ProcessCompleted?.Invoke(this, e);} This is a protected method used to raise the event. The `?.Invoke` syntax ensures that the event is only invoked if there are subscribers. 4. Subscribe and unsubscribe from the event: process.ProcessCompleted += Process_ProcessCompleted; The subscriber uses the `+=` operator to subscribe to the event and defines the event handler `Process_ProcessCompleted`. ## Example ## Example 1 using System; namespace SimpleEvent { using System; /***********Publisher Class***********/ public class EventTest { private int value; public delegate void NumManipulationHandler(); public event NumManipulationHandler ChangeNum; protected virtual void OnNumChanged() { if (ChangeNum != null) { ChangeNum(); /* Event is raised */ } else { Console.WriteLine("event not fire"); Console.ReadKey(); /* Press Enter to continue */ } } public EventTest() { int n = 5; SetValue(n); } public void SetValue(int n) { if (value != n) { value = n; OnNumChanged(); } } } /***********Subscriber Class***********/ public class subscribEvent { public void printf() { Console.WriteLine("event fire"); Console.ReadKey(); /* Press Enter to continue */ } } /***********Trigger***********/ public class MainClass { public static void Main() { EventTest e = new EventTest(); /* Instantiate object, first time no event is raised */ subscribEvent v = new subscribEvent(); /* Instantiate object */ e.ChangeNum += new EventTest.NumManipulationHandler(v.printf); /* Register */ e.SetValue(7); e.SetValue(11); } } } When the above code is compiled and executed, it produces the following result: event not fire event fire event fire This example provides a simple application for troubleshooting a hot water boiler system. When a maintenance engineer inspects the boiler, the boiler's temperature and pressure are automatically recorded to a log file along with the engineer's notes. ## Example 2 using System; using System.IO; namespace BoilerEventAppl { // Boiler class class Boiler { public int Temp { get; private set; } public int Pressure { get; private set; } public Boiler(int temp, int pressure) { Temp = temp; Pressure = pressure; } } // Event publisher class DelegateBoilerEvent { public delegate void BoilerLogHandler(string status); // Define the event based on the above delegate public event BoilerLogHandler BoilerEventLog; public void LogProcess() { string remarks = "O.K."; Boiler boiler = new Boiler(100, 12); int temp = boiler.Temp; int pressure = boiler.Pressure; if (temp > 150 || temp < 80 || pressure 15) { remarks = "Need Maintenance"; } OnBoilerEventLog($"Logging Info:n Temperature: {temp}n Pressure: {pressure}n Message: {remarks}"); } protected void OnBoilerEventLog(string message) { BoilerEventLog?.Invoke(message); } } // This class keeps provisions for writing to a log file class BoilerInfoLogger : IDisposable { private readonly StreamWriter _streamWriter; public BoilerInfoLogger(string filename) { _streamWriter = new StreamWriter(new FileStream(filename, FileMode.Append, FileAccess.Write)); } public void Logger(string info) { _streamWriter.WriteLine(info); } public void Dispose() { _streamWriter?.Close(); } } // Event subscriber public class RecordBoilerInfo { static void Logger(string info) { Console.WriteLine(info); } static void Main(string[] args) { using (BoilerInfoLogger fileLogger = new BoilerInfoLogger("e:boiler.txt")) { DelegateBoilerEvent boilerEvent = new DelegateBoilerEvent(); boilerEvent.BoilerEventLog += Logger; boilerEvent.BoilerEventLog += fileLogger.Logger; boilerEvent.LogProcess(); } Console.ReadLine(); } } } When the above code is compiled and executed, it produces the following result: Logging info:Temperature 100Pressure 12Message: O. K
← Csharp CollectionCsharp Delegate β†’