In C#, use the event
keyword to declare events. An event is associated with a delegate type, allowing multiple methods to be called when the event is triggered. You can also specify access modifiers to control the event visibility, enhancing encapsulation.
using System;public class Car{// Declare the event using a delegate typepublic event EventHandler EngineStarted;public void StartEngine(){Console.WriteLine("Engine started.");// Trigger the eventEngineStarted?.Invoke(this, EventArgs.Empty);}}class Program{static void Main(){Car car = new Car();car.EngineStarted += (sender, e) => Console.WriteLine("Listener: The engine has been started!");car.StartEngine();}}
C# leverages EventHandler<T>
to handle events with specific data types, ensuring compile-time type safety. This method allows developers to prevent runtime errors by enforcing type consistency at compile time. In the snippet, note how MyEventArgs
enforces type safety for our event data.
// Define event data classpublic class MyEventArgs : EventArgs {public string Message { get; set; }}// Define a class with an eventpublic class Publisher {public event EventHandler<MyEventArgs> OnDataReceived;public void RaiseEvent(string message) {OnDataReceived?.Invoke(this, new MyEventArgs { Message = message });}}// Subscriber classpublic class Subscriber {public void OnDataReceived(object sender, MyEventArgs e) {Console.WriteLine($"Received message: {e.Message}");}}// Usage Examplevar publisher = new Publisher();var subscriber = new Subscriber();publisher.OnDataReceived += subscriber.OnDataReceived;publisher.RaiseEvent("Hello, EventHandling!");
C#
In C#, events are raised using the Invoke()
method after null checking. This ensures only subscribed methods are called when an event occurs. Use this to trigger actions across your application efficiently.
using System;class AlarmClock {public event EventHandler AlarmRang;public void RingAlarm() {AlarmRang?.Invoke(this, EventArgs.Empty); // Check for null and invoke}}class Program {static void Main() {AlarmClock myClock = new AlarmClock();myClock.AlarmRang += (sender, e) => Console.WriteLine("Alarm is ringing!");myClock.RingAlarm();}}
Events in C# enable communication between objects using the publisher-subscriber pattern. This allows one object, the publisher, to maintain a list of subscribers and notify them of changes, ensuring loose coupling. Above, an example demonstrates how an event can be created, published, and subscribed to.
using System;public class Publisher {// Declare the event using EventHandlerpublic event EventHandler EventOccurred;public void TriggerEvent() {Console.WriteLine("Event is about to occur!");// Check if there are any subscribersEventOccurred?.Invoke(this, EventArgs.Empty);}}public class Subscriber {public void OnEventOccurred(object sender, EventArgs e) {Console.WriteLine("Event has been handled.");}}public class Program {public static void Main() {Publisher publisher = new Publisher();Subscriber subscriber = new Subscriber();// Subscribe to the eventpublisher.EventOccurred += subscriber.OnEventOccurred;// Trigger the eventpublisher.TriggerEvent();}}
In C#, you use the +=
operator to subscribe and the -=
operator to unsubscribe an event handler to an event. This allows your program to respond dynamically to events, like button clicks or data changes.
using System;public class EventExample{public event EventHandler ButtonClicked;public void ClickButton(){if (ButtonClicked != null)ButtonClicked(this, EventArgs.Empty);}public static void Main(string[] args){EventExample example = new EventExample();// Subscribe to the eventexample.ButtonClicked += Example_ButtonClicked;// Trigger the eventexample.ClickButton();// Unsubscribe from the eventexample.ButtonClicked -= Example_ButtonClicked;}private static void Example_ButtonClicked(object sender, EventArgs e){Console.WriteLine("Button was clicked!");}}
In C#, event handlers are implemented using method group conversions or lambda expressions that match a delegate signature. This allows for responsive, dynamic applications by handling events such as clicks and actions effectively. Use +=
to attach a handler to an event.
using System;class Program {static void Main() {// Create a buttonButton myButton = new Button();// Attach an event handler using a method groupmyButton.Click += ButtonClicked;// Attach an event handler using a lambda expressionmyButton.Click += (sender, e) => {Console.WriteLine("Button clicked with lambda!");};// Simulate button clickmyButton.SimulateClick();}// Event handler methodstatic void ButtonClicked(object sender, EventArgs e) {Console.WriteLine("Button clicked!");}}class Button {// Define the Click event using EventHandler delegatepublic event EventHandler Click;// Method to simulate the button clickpublic void SimulateClick() {Click?.Invoke(this, EventArgs.Empty);}}
In C#, interfaces can declare events that implementing classes must define. This ensures a consistent way to handle events across various classes, promoting uniformity and modularity in your code. Implementing classes guarantee they support and implement the events outlined by the interface, aiding structure and communication in complex applications.
public interface IEventNotifier {event EventHandler Notify;}public class EventNotifier : IEventNotifier {public event EventHandler Notify;public void TriggerEvent() {if (Notify != null) {Notify(this, EventArgs.Empty);}}}
In C#, use the protected virtual OnEventName()
method to define and raise events in base classes. This pattern allows derived classes to override the method and handle events seamlessly. By default, this method checks for event subscribers, preventing null reference exceptions.
public class BaseClass{public event EventHandler MyEvent;protected virtual void OnMyEvent(){// Check if there are subscribersMyEvent?.Invoke(this, EventArgs.Empty);}}
In C#, custom EventArgs
classes inherit from the EventArgs
base class to pass extra data when raising events. This allows sending specific data alongside standard event notifications by creating a new class derived from EventArgs
.
using System;// Define a custom EventArgs classpublic class TemperatureChangedEventArgs : EventArgs{public double NewTemperature { get; }public TemperatureChangedEventArgs(double newTemperature){NewTemperature = newTemperature;}}// Publisher classpublic class Thermostat{public event EventHandler<TemperatureChangedEventArgs> TemperatureChanged;private double _currentTemperature;public double CurrentTemperature{get => _currentTemperature;set{if (Math.Abs(_currentTemperature - value) > 0.01){_currentTemperature = value;OnTemperatureChanged(new TemperatureChangedEventArgs(value));}}}protected virtual void OnTemperatureChanged(TemperatureChangedEventArgs e){TemperatureChanged?.Invoke(this, e);}}// Subscriber examplepublic class Display{public void Register(Thermostat thermostat){thermostat.TemperatureChanged += OnTemperatureChanged;}private void OnTemperatureChanged(object sender, TemperatureChangedEventArgs e){Console.WriteLine($"Temperature changed to: {e.NewTemperature}°C");}}
The EventHandler
delegate pattern in C# requires methods to include two specific parameters: object sender
for the event source and EventArgs e
for event data. This pattern standardizes how events are handled in applications, promoting consistency across event handling logic.
using System;class Program{// Event declaration using EventHandlerpublic event EventHandler ExampleEvent;// Method matching EventHandler signatureprotected virtual void OnExampleEvent(EventArgs e){ExampleEvent?.Invoke(this, e);}static void Main(){Program program = new Program();// Subscribing to the eventprogram.ExampleEvent += (sender, e) =>{Console.WriteLine("Event Triggered!");};// Triggering the eventprogram.OnExampleEvent(EventArgs.Empty);}}