воскресенье, 14 марта 2010 г.

C# 4.0 events. Small implementation change

C# 4.0 is going to change the way how event handlers addition and removal is implemented. From it birth C# compiler used to add special accessor methods to every event which didn’t have its own accessors declared. For thread safety those auto accessors had MethodImpl(MethodImplOptions.Synchronized) attribute defined on them. Using that attribute on publicly accesible methods is considered harmful because at runtime those methods are wrapped in lock(this) or lock(typeof([TypeDeclaringTheEvent])) for static events which, in its turn, is a bad practice as well.

In C# 4.0 event accessors don't use explicit locking, but implement what can be considered as optimistic locking. Look at the following:

//pre 4.0
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_Disposed(EventHandler value)
{
    this.Disposed = (EventHandler) Delegate.Combine(this.Disposed, value);
}

// 4.0
public void add_Disposed(EventHandler value)
{
    EventHandler handler2;
    EventHandler disposed = this.Disposed;

    do
    {
        handler2 = disposed;
        EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value);
        disposed = Interlocked.CompareExchange(ref this.Disposed, handler3, handler2);
    }
    while (disposed!= handler2);
}

With the new algorithm we don't have to have one private object for each public event just to protect them from lockin issues. Besides that it is a little bit lighter and more performant. Delegate type itself hasn't changed at all. Delegates have been immutable reference types from the very begining. The only question I have: Why they didn't do that in the first place!?

More details in C# compiler team member's blog:
Field-like Events Considered Harmful
Events get a little overhaul in C# 4, Part II: Semantic Changes and +=/-=

2 комментария: