Note that only field-like events can be used in this way:
SomeEvent = SomeMethod;
SomeEvent += SomeMethod; and SomeEvent -= SomeMethod; on the other hand can be used with all events, and they call the add and remove accessors of SomeEvent respectively.
Here's what a field-like event is, from the language spec:
Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. To be used in this way, an event [...] must not explicitly include event_accessor_declarations. Such an event can be used in any context that permits a field. The field contains a delegate which refers to the list of event handlers that have been added to the event. If no event handlers have been added, the field contains null.
In general, a field like event does not have explicit add and remove accessors.
Notice how they have a delegate-typed field storing the list of event handlers. SomeEvent = SomeMethod; basically sets the field to a delegate whose invocation list contains only SomeMethod. This means that all the previous handlers in the list are discarded. If you are wondering how a method name can be converted to a delegate, see method group conversions.
The add and remove accessors of field-like events are automatically generated:
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 addition and removal operations are thread safe, and may (but are not required to) be done while holding the lock on the containing object for an instance event, or the type object for a static event.
The spec doesn't say exactly how, so that's up to the implementation to decide. On SharpLab, we can see that one implementation would be:
private EventHandler m_SomeEvent;
private event EventHandler SomeEvent
{
[CompilerGenerated]
add
{
EventHandler eventHandler = this.SomeEvent;
while (true)
{
EventHandler eventHandler2 = eventHandler;
EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value);
eventHandler = Interlocked.CompareExchange(ref this.SomeEvent, value2, eventHandler2);
if ((object)eventHandler == eventHandler2)
{
break;
}
}
}
[CompilerGenerated]
remove
{
EventHandler eventHandler = this.SomeEvent;
while (true)
{
EventHandler eventHandler2 = eventHandler;
EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value);
eventHandler = Interlocked.CompareExchange(ref this.SomeEvent, value2, eventHandler2);
if ((object)eventHandler == eventHandler2)
{
break;
}
}
}
}
Note the field m_SomeEvent, and the calls to Delegate.Remove and Delegate.Combine - those are what adds the new handler to the list of handlers, and removes a handler from the list of handlers.
So can we use += instead of = or is it bad to use += when you only have to subscribe event to single method?
It's not bad to use += when you subscribe to only one method. In fact, I would recommend you to use +=. You may say "I only want to subscribe to a single method" now, but you never know when that's going to change :)