|
| 1 | +As you continue developing the retail store application, your team is eager to improve the way the app responds to user actions like button and menu selections. After setting up basic functionality for actions for adding items to a cart and completing a purchase, it's time to explore how events in C# can streamline these processes. |
| 2 | + |
| 3 | +Events allow different parts of your application to communicate effectively. When users select a button or menu item, events ensure tasks like updating inventory or applying discounts happen smoothly. The use of events not only keeps your code organized but also makes it easier to adapt and expand your application as new features are added. By understanding how events work and their relationship with delegates, you're able to build a more flexible and maintainable application. |
| 4 | + |
| 5 | +## Understand events |
| 6 | + |
| 7 | +Events let one part of a program inform other parts when something important occurs. The part that sends out the event is called the **publisher**, and the parts that respond to the event are called **subscribers**. For instance, events are often used in programs with graphical user interfaces to react to things like button or menu selections. |
| 8 | + |
| 9 | +The following diagram illustrates the relationship between a publisher and subscribers in an event-driven model: |
| 10 | + |
| 11 | +:::image type="content" source="../media/publisher-subscriber.png" alt-text="Diagram showing publisher and subscriber relationship."::: |
| 12 | + |
| 13 | +- The **publisher** raises an event when a specific action occurs, such as the selection of a button. |
| 14 | +- The **subscribers** handle the event by executing their respective event handler methods. |
| 15 | + |
| 16 | +This model ensures that the publisher and subscribers remain loosely coupled, allowing for greater flexibility and maintainability. |
| 17 | + |
| 18 | +**Key properties of events** |
| 19 | + |
| 20 | +- Publishers determine when an event is raised, and subscribers decide what action to take in response. |
| 21 | +- An event can have multiple subscribers, and a subscriber can handle multiple events. |
| 22 | +- Events without subscribers are never raised. |
| 23 | + |
| 24 | +**Example: A simple button click event** |
| 25 | + |
| 26 | +```csharp |
| 27 | +public class Button |
| 28 | +{ |
| 29 | + public event EventHandler? Selected; // Nullable to indicate no subscribers initially |
| 30 | +
|
| 31 | + public void OnClick() |
| 32 | + { |
| 33 | + // If subscribers exist, ?.Invoke syntax triggers an event |
| 34 | + Selected?.Invoke(this, EventArgs.Empty); |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +// Subscribing to the event |
| 39 | +Button button = new Button(); |
| 40 | +button.Selected += (sender, e) => Console.WriteLine("Button Selected!"); |
| 41 | + |
| 42 | +// Triggering the event |
| 43 | +button.OnClick(); // Output: "Button Selected!" |
| 44 | +``` |
| 45 | + |
| 46 | +In this example, the `Selected` event is declared as `EventHandler?`, using a nullable reference type which explicitly indicates that the event might not have any subscribers, ensuring that the code handles such scenarios gracefully. The `?.Invoke` syntax further ensures that the event is only raised if there are subscribers, preventing potential `NullReferenceException` errors. |
| 47 | + |
| 48 | +Lambda expressions (`=>`) are used in the subscription to define the event handler inline. Lambda expressions provide a concise and readable way to define event handlers, especially when the logic is simple and doesn't require a separate method. |
| 49 | + |
| 50 | +## Delegates: The foundation of events |
| 51 | + |
| 52 | +Delegates are type-safe function pointers that allow methods to be passed as parameters and invoked dynamically. Events in C# are built on the foundation of delegates, which define the method signature for event handlers. |
| 53 | + |
| 54 | +**How delegates relate to events**: |
| 55 | + |
| 56 | +- Delegates define the method signature that event handlers must match. |
| 57 | +- Events use delegates to notify subscribers when something significant occurs. |
| 58 | + |
| 59 | +**Example: Delegate behind an event** |
| 60 | + |
| 61 | +```csharp |
| 62 | +// Define a delegate |
| 63 | +public delegate void ButtonClickedHandler(object sender, EventArgs e); |
| 64 | + |
| 65 | +// Use the delegate in an event |
| 66 | +public class Button |
| 67 | +{ |
| 68 | + public event ButtonClickedHandler Clicked; |
| 69 | + |
| 70 | + public void OnClick() |
| 71 | + { |
| 72 | + Clicked?.Invoke(this, EventArgs.Empty); |
| 73 | + } |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +> [!NOTE] |
| 78 | +> Delegates provide the type-safe mechanism that events rely on to notify subscribers. |
| 79 | +
|
| 80 | +## Events design |
| 81 | + |
| 82 | +The design of events in C# aims to facilitate minimal coupling between components while ensuring flexibility and ease of use. |
| 83 | + |
| 84 | +**Goals of event design** |
| 85 | + |
| 86 | +- **Minimal coupling**: Events enable interaction between an event source and an event sink without requiring tight dependencies. Minimal coupling, using events, is especially useful when components developed by different teams or updated independently. |
| 87 | +- **Ease of subscription and unsubscription**: The syntax for subscribing (`+=`) and unsubscribing (`-=`) is straightforward. |
| 88 | +- **Support for multiple subscribers**: Events can have zero, one, or multiple subscribers, making them versatile for various scenarios. |
| 89 | + |
| 90 | +Events are often used in scenarios where user actions or system changes need to be communicated across components. For example, a `Closing` event might allow subscribers to cancel the close operation or modify its behavior. |
0 commit comments