Increasing activity in C #: performance and elegance

Being used to VB.NET, I’m used to "just raise events." Of course, user events are different, but with "regular" events - I don't need to check if the delegate was Nothing before the promotion.

With C #, I repeat this pattern:

 if (myHandler != null) { myHandler(this, new EventArgs()); } 

I thought the following pattern might turn out to be more elegant:

  • myHandler is initialized with an empty lambda: myHandler = (sender, e) => { };
  • myHandler is expected to never be null, so the raise will just become: myHandler(this, new EventArgs());

Will this template be more or less effective than the previous one? Are there any other significant considerations that I should consider?

+4
source share
4 answers

I think the performance difference between the two approaches is not so great as to be relevant. Anyway, I would say that a zero check is cheaper than calling a method through a delegate, even if it does not work.

Speaking of elegance , it should be pointed out that the RaiseEvent keyword in VB.NET automatically expands the compiler to the exact same design that you should write yourself in C #:

 If (Not MyEvent Is Nothing) Then MyEvent.Invoke(New EventArgs()) End If 

If you want to avoid repeating this construct in all your code, you can encapsulate it in several extension ways:

 public static void RaiseEvent(this EventHandler source, object sender) { if (source != null) { source.Invoke(sender, new EventArgs()); } } public static void RaiseEvent<T>(this EventHandler<T> source, object sender, T eventArgs) where T : EventArgs { if (source != null) { source.Invoke(sender, eventArgs); } } 

So you can just say:

 myEvent.RaiseEvent(this); myOtherEvent.RaiseEvent(this, new SomeEventArgs()); 

which is semantically equivalent to the style used in VB.NET.

+1
source

This is something extra in construction, but it will not be a huge overhead. It should be noted that some serialization schemes, such as DataContractSerializer (WCF), do not run field constructors or initializers, so in the end they may not be empty. Personally, if most of your events are EventHandler , I might be tempted to use the extension method:

 public static void SafeInvoke(this EventHandler handler, object sender) { if (handler != null) handler(sender, EventArgs.Empty); } 

then

 SomeEvent.SafeInvoke(this); 

at least frankly, I rarely have a problem with the simple use of null-check; p

Another drawback is that if you have enough events in which this is a problem, you should probably use an EventHandlerList instead, and this approach will not work with an EventHandlerList .

+5
source

A common practice is to use the OnEventName protected virtual methods, where you can check if the event is null and raise it:

 protected virtual void OnEventName(parameters) { if (EventName != null) EventName(this, new EventNameEventArgs(parameters); } 

This allows you to have all the code to create events in one place (without duplicating the zero check) and redefine it later if necessary. Therefore, I do not see any benefit from adding one event handler in an event if you have one zero check for the event.

BTW a shorter way to add a stub handler is myHandler = delegate {};

+2
source

Do not think that there is a significant difference between the 1st and 2nd cases, at least not so much for their consideration. If delegates are used too often, the absence of if (myHandler != null) could, by the way, lead to some performance advantages. Therefore, if you are sure that the handler is never null , get rid of this control and basically you did.

+1
source

Source: https://habr.com/ru/post/1402185/


All Articles