C# allows us to create custom event accessors.
Action _custom;
public event Action Custom
{
add { _custom = (Action)Delegate.Combine( _custom, value ); }
remove { _custom = (Action)Delegate.Remove( _custom, value ); }
}
If you don't specify them, the compiler creates them for you. C# language spec:
When compiling a field-like event, the compiler automatically creates storage to hold the delegate, and creates accessors for the event that add or remove event handlers to the delegate field.
The decompiled source code using dotPeek for a simple public event Action Public;
looks as follows:
private Action Public;
public event Action Public
{
add
{
Action action = this.Public;
Action comparand;
do
{
comparand = action;
action = Interlocked.CompareExchange<Action>(
ref this.Public, comparand + value, comparand);
}
while (action != comparand);
}
remove
{
Action action = this.Public;
Action comparand;
do
{
comparand = action;
action = Interlocked.CompareExchange<Action>(
ref this.Public, comparand - value, comparand);
}
while (action != comparand);
}
}
Noteworthy is that the field and the event use the same name. This has led some people to conclude that you can find information about the backing field during reflection by looking up the field in the class with the same name as the event. I implemented this as follows:
public static FieldInfo GetFieldInfo( this EventInfo eventInfo )
{
Contract.Requires( eventInfo != null );
return eventInfo.DeclaringType.GetField(
eventInfo.Name,
BindingFlags.DeclaredOnly | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic );
}
This works, but raises the question: Is the backing field of a compiler generated event always guaranteed to use the same name as the event?
It's not possible to create custom event accessors which access a delegate with the same name using Visual Studio. This results in the message: "Member with the same name is already declared." I am wondering whether you could conclude that any event for which no backing delegate with the same name is available is an event with custom accessors.