Custom Event Accessors (`add` / `remove`) with Synchronization
1Concept
Custom event accessors (`add` and `remove`) allow developers to control how delegate listeners are stored, providing thread-safe lock management or integration with external event buses.
2Architecture Diagram
event Action MyEvent ├── add ──> Interlocked.CompareExchange (Lock-free thread-safe subscriber append) └── remove ──> Interlocked.CompareExchange (Lock-free thread-safe subscriber remove)
3Code Example
C# 13 & .NET 9
using System;
using System.Threading;
public class CustomEventStore
{
private Action<string>? _handlers;
public event Action<string> OnMessage
{
add
{
Action<string>? current = _handlers;
Action<string>? updated;
do
{
updated = (Action<string>?)Delegate.Combine(current, value);
current = Interlocked.CompareExchange(ref _handlers, updated, current);
} while (current != updated);
}
remove
{
Action<string>? current = _handlers;
Action<string>? updated;
do
{
updated = (Action<string>?)Delegate.Remove(current, value);
current = Interlocked.CompareExchange(ref _handlers, updated, current);
} while (current != updated);
}
}
public void Broadcast(string msg) => _handlers?.Invoke(msg);
}
public class CustomAccessorDemo
{
public static void Main()
{
var store = new CustomEventStore();
store.OnMessage += m => Console.WriteLine($"Subscriber A: {m}");
store.Broadcast("Broadcast message dispatched!");
}
}4Expected Output
Subscriber A: Broadcast message dispatched!
5Key Takeaways
- ✓Default C# events use `Interlocked.CompareExchange` under the hood for lock-free thread safety.
- ✓Custom accessors let you route events to distributed message brokers (Kafka/RabbitMQ).
- ✓Avoid throwing exceptions inside `add`/`remove` accessors.