Phase 11 of 30 · Topic 11.4

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.