TOP KEK
TOP KEK

Reputation: 2651

Internal design of event in C#

Just finished reading Jon Skeet's article about events and delegates and got a question.

Lets say first in the code I declare an event

public event EventHandler MyEvent

Then I want to raise it in the code in a manner

if (MyEvent != null)
    Myevent(this,EvtArgs.Empty);

Jon says that in fact MyEvent looks somehow like this:

private EventHandler _myEvent;

public event EventHandler MyEvent
{
    add
    {
        lock (this)
        {
            _myEvent += value;
        }
    }
    remove
    {
        lock (this)
        {
            _myEvent -= value;
        }
    }        
} 

The question is what really happens when I compare MyEvent != null ? As I understand in fact it compares _myEvent to null, but I am not sure.

Upvotes: 3

Views: 223

Answers (3)

aKzenT
aKzenT

Reputation: 7895

Internally an event is a set of add/remove methods with a backing field of type MulticastDelegate You get this field when you are asking for MyEvent outside of the class and compare this instance to null.

See also this post: How do C# Events work behind the scenes?

Edit: Also, as pointed out by Jon already, you don't get a field in case you provide the add/remove methods yourself.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500055

If you implement custom add/remove accessors, you won't be able to compare MyEvent to null in the first place, because it will only be an event - it doesn't have a value as such, only add/remove accessors. You would have to use your declared field (_myEvent in the sample above) instead.

You can only do the comparison using the event name when you're using field-like events, where you end up with (effectively) a field and an event with the same name. (The compiled code doesn't have to actually reuse the event name for the field name, but it has to look like it does when you're compiling.)

Note that using this:

if (MyEvent != null)
    MyEvent(this,EvtArgs.Empty);

isn't thread-safe, as MyEvent could become null between the check and the invocation. You should use:

EventHandler handler = MyEvent;
if (handler != null)
{
    handler(this, EventArgs.Empty);
}

Also note that the part about field-like events locking on this is now slightly outdated; in C# 4 thread-safety is achieved using a lock-free compare-exchange mechanism.

Upvotes: 5

huysentruitw
huysentruitw

Reputation: 28091

When there is no handler subscribed to MyEvent, MyEvent will equal null. So before firing the event, you first check if there is at least one handler subscribed to it.

Upvotes: 1

Related Questions