C#
Observer
Learn event-based notification with the Observer pattern.
Observer pattern
Observer lets a subject notify subscribed objects when its state changes. In C# this is built in through the event keyword and the EventHandler<T> delegate.
Example: a Stock class raises a PriceChanged event when the price changes. A StockMonitor subscribes to the event and prints on each change. The subject does not need to know its observers; it just fires the event.
event and EventHandler<T>
In C# the event keyword lets a delegate be raised only from inside the defining class. Outside code can only subscribe with += or unsubscribe with -=. EventHandler<T> standardizes the signature (sender and event data).
A property often acts as the trigger: the set block stores the new value, then raises the event with PriceChanged?.Invoke(this, value). The ?. skips the call when there are no subscribers.
Exercise Build Stock and StockMonitor
Define class Stock. The Symbol property is set from the constructor. The Price property's set block stores the new value and raises the event with PriceChanged?.Invoke(this, value). Declare public event EventHandler<decimal> PriceChanged. class StockMonitor's constructor takes a Stock, subscribes to PriceChanged with a lambda, and writes "{symbol}: {price}" via Console.WriteLine. In Main, create new Stock("ACME"), attach a monitor, and set Price = 150m.
Show example solution
Define class Stock { public string Symbol { get; } public Stock(string s) => Symbol = s; private decimal _price; public decimal Price { get => _price; set { _price = value; PriceChanged?.Invoke(this, value); } } public event EventHandler<decimal> PriceChanged; }. In StockMonitor's constructor: stock.PriceChanged += (s, p) => Console.WriteLine($"{stock.Symbol}: {p}"); In Main: var stock = new Stock("ACME"); var monitor = new StockMonitor(stock); stock.Price = 150m;
Example solution:
using System;
class Stock
{
public string Symbol { get; }
public Stock(string symbol) => Symbol = symbol;
private decimal _price;
public decimal Price
{
get => _price;
set
{
_price = value;
PriceChanged?.Invoke(this, value);
}
}
public event EventHandler<decimal> PriceChanged;
}
class StockMonitor
{
public StockMonitor(Stock stock)
{
stock.PriceChanged += (s, price) =>
Console.WriteLine($"{stock.Symbol}: {price}");
}
}
class Program
{
static void Main()
{
var stock = new Stock("ACME");
var monitor = new StockMonitor(stock);
stock.Price = 150m;
}
}
Test yourself
-
Match Observer terms
- Subject
- Notification source
- Observer
- Notification receiver
- Subscribe
- Adds an observer
- Notify
- Tells all observers
-
What is the role of the Observer?
- Receives notice when the Subject changes
- Creates the single instance
- Seals the class
- Makes object creation easier
Show answer
Receives notice when the Subject changes — Correct. The Observer subscribes to the Subject's change event and receives notice.
-
Complete the event declaration
public ____ EventHandler<decimal> PriceChanged;
Show answer
public event EventHandler<decimal> PriceChanged;
Next lesson: Decorator