3

Raising events in thread-safe way (in order to avoid NullReferenceException) requires copying the event delegate before calling it:

EventHandler copy = TheEvent;
if (copy != null)
    copy(this, EventArgs.Empty);

or using the null-conditional operator and Volatile.Read in C# 6 as proposed by Jon Skeet:

Volatile.Read(ref TheEvent)?.Invoke(this, EventArgs.Empty);

(See C# Events and Thread Safety for the discussion).

This is tedious and error-prone. Would it not make sense to add a raise keyword to C# so that the above pattern (or an improved one chosen by the C# compiler team) would be taken care of transpararently by the compiler, e.g.

raise TheEvent(this, EventArgs.Empty);

This would be a syntactic convenience in line with using and async/await that would solve the confusion around the proper way of raising events in a conclusive way.

What are the downsides?

EDIT

Thanks to all of you for the feedback - adding another keyword is indeed a bit extreme.

However, as the "standard" way of raising events is still lacking and as many people like the Raise() extension method, I proposed to add it to mscorlib at the Visual Studio UserVoice channel.

Community
  • 1
  • 1
mrts
  • 16,697
  • 8
  • 89
  • 72
  • 1
    The using and async/await keywords solve much more complex problems. `using` allows you to mimic C++'s RAII style which is more than a few lines due to exceptions (basically wrap everything in a Try/Finally) and `async`/`await` is huge. My guess is that a `raise` keyword is really pretty tiny and is actually a performance hit if you know that the event will never be modified concurrently. Completely my opinion so that's why this is a comment not an answer. – NtscCobalt Mar 23 '13 at 21:21
  • 1
    It's still not threadsafe. It's only threadsafe *with regards to avoiding `NullReferenceException`*. It's still not threadsafe with regards to raising events after they've been unsubscribed from another thread, or not raising events after they've been subscribed to from another thread. The only *strictly threadsafe* way of using events is to subscribe, unsubscribe, and raise them from the same thread. In which case making a copy is unnecessary. – Stephen Cleary Mar 23 '13 at 21:56
  • The CLR already defines a raise *accessor* for events. It doesn't require a keyword, add and remove are not keywords either. The C# team just chose to not implement it. They don't like hiding thread-unsafe code. – Hans Passant Sep 13 '13 at 20:15

1 Answers1

2

Is it really that error-prone or confusing? Even if they did add such a keyword, they'd still have to keep the old way of raising events for compatibility and you'd have to know the right way to raise the event. You can create an extension method like the following to do most of the work:

public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
  if (handler != null)
  {
    handler(sender, args); 
  }
}

I'd rather see the compiler team work on making the impossible possible than reducing my code base by a few lines.

Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • 1
    It is generally perceived as confusing: quoting http://stackoverflow.com/questions/231525/raising-c-sharp-events-with-an-extension-method-is-it-bad *We're all familiar with the horror that is C# event declaration.*, http://stackoverflow.com/questions/840715/the-proper-way-of-raising-events-in-the-net-framework *Currently "Avoid checking for null event handlers" is at the top of the answers to the post titled Hidden Features of C# and it contains severely misleading information.* etc – mrts Mar 23 '13 at 21:31