While playing around in VS 2015, i was creating a property and mistyped prior to hitting tab and it gave me what appears to be a very clean simple method for creating an event. I am unsure how to use this to accept additional parameters to pass it data (as I usually want to pass data when raising an event with information about what is in progress, or what was done)
The code it gave is as follows :
public event EventHandler<EventArgs> MyEvent;
protected virtual void OnMyEvent(EventArgs e)
{
EventHandler<EventArgs> handler = MyEvent;
if (handler != null)
handler(this, e);
}
At first glance it is similar to most examples however this method does not appear to require a delegate to operate. Compare with the following example from How to call an event manually in C#?
public delegate void MyEventHandler(object sender, MyEventArgs e)
public event MyEventHandler MyEvent;
public void RaisesMyEvent()
{
if(MyEvent != null) //required in C# to ensure a handler is attached
MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
}
What I would like to know, in light of having more elegant (clean) code, is the method that microsoft provided (first method in this question) better (it seems cleaner), and if so, how could I adjust it slightly to accept a string in addition to standard event args and/or extend the eventargs to pass information ?
To pass custom arguments on an EventHandler, you would create your own class derived from EventArgs and change the declaration like so:
public event EventHandler<MyCustomEventArgs> MyEvent;
Alternatively, if you don't like having object sender in your handlers, you can do:
public event Action<MyCustomEventArgs> MyEvent;
or even
public event Action<string> MyEvent;
As far as the invocation, Microsoft's is better. The reason is that the null check you wrote isn't thread-safe. Storing off the handler before doing the null check ensures that you don't invoke a null method.
Alternatively, use C# 6 invocations and take advantage of the null conditional operator:
MyEvent?.Invoke(whateverArgs);
The code that Visual Studio auto-generated for you is actually better for one small condition:
public void RaisesMyEvent()
{
if(MyEvent != null) //required in C# to ensure a handler is attached
// Now if someone in another thread sets MyEvent to null the next line will still execute
MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
// And throw a NullReferenceException
}
This code has a race condition. It's fairly rare to hit it, but it is possible. The Visual Studio boilerplate code avoids this race condition by making a local copy of the event handler before calling it.
As for how to pass more parameters to the event handler:
There are multiple ways, but the 'standard' way is to create an class that extends EventArgs. For instance, PaintEventArgs extends EventArgs and adds a Graphics and Rectangle properties for the OnPaint handler to use.
I'd follow that basic pattern by creating a MyEventArgs class based off EventArgs, and adding the properties your method will need to use.
Just replace EventArgs with your own class:
class MyEventArgs : EventArgs
{
public string Text { get; private set; }
public MyEventArgs(string text)
{
Text = text;
}
}
The EventHandler<T> generic delegate type will accept EventArgs or any subclass of EventArgs.
Then when you call OnMyEvent(), just pass an instance of your class with the data you want to deliver with the event.
I agree with the other notes regarding thread-safe invocation. This isn't always required, but it's simple enough to implement and the IDE-provided version is safe while yours is not.
Related
I want to ask the different between EventHandler and EventHandler<T>.
Previously I have implemented a EventHandler, with a custom EventArgs which can be passed to the parent page from the user control.
I thought I need to apply EventHandler< T >, however it can be implemented by using EventHandler. (in fact there is weird error when I trying to apply EventHandler<T>, the program is worked but error is shown in the IDE which I couldn't solve [C# Custom EventHandler ])
Thus, I want to know in what situation I need to apply EventHandler < T > ?
public event EventHandler AppendProcess;
public event EventHandler<MyEventArg> AppendProcess;
---Update---
this is how I invoke the event in the user control (as i said, i can pass object to parent page by doing this (although i don't know if it is correct to do so)
if (AppendProcess == null) { }
else
AppendProcess(this, new Common.WinLose_ProgressStage(Common.WinLose_SP_Parameter.upper, displayLevel + 1,
(int)Common.WinLose_Level.lvChild4, thename, refundratio,
selfproportion, -1, -1, loadlevel, isPlayer, betsource, gamecategory, false));
EventHandler<T> is just a generic EventHandler type, which avoids you having to declare a new delegate type for each kind of EventArgs you want to use.
Consider Control.KeyPress for example. It's declared as an event of type KeyPressEventHandler. That delegate is just declared as:
public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e)
If EventHandler<T> (and generics) had been around when that was created, the event could have been declared as an EventHandler<KeyPressEventArgs> instead, saving a delegate declaration. There are many, many delegates which are just like EventHandler, and only vary in the type of the second parameter - EventHandler<T> avoids that redundancy.
No if you don't have your own custom EventArgs subclass, there's no reason to use EventHandler<T>... but if you do, it's much better to use it, so that the method handling the event receives your custom EventArgs subclass in a strongly-typed way.
As an aside, your way of invoking the event handler isn't thread-safe. Another thread could unsubscribe the final event handler after your nullity check. If you're using C# 5, you should write it as:
var handler = AppendProcess;
if (handler != null)
{
handler(this, new Common.WinLose_ProgressStage(...));
}
If you're using C# 6 or later, you can use the null conditional operator:
// If AppendProcess is null, the arguments won't even be evaluated
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...));
EventHandler<T> is the generic variant of EventHandler. Usually, you would override EventArgs and EventHandler to come up with an own event type. You still need to derive EventArgs if you want to pass in custom properties to the e argument, but you don't need to create a custom delegate for EventHandler any more. You now can just say:
public event EventHandler<SomeEventArgs> SomeEvent;
Which is more convenient than:
public delegate void SomeEventHandler(object sender, SomeEventArgs e);
public event SomeEventHandler SomeEvent;
When your delegate signature doesn't change, EventHandler<T> is much more straightforward to use.
From your other question:
Common.WinLose_ProgressStage wps = (Common.WinLose_ProgressStage)e;
That's a cast that could potentially fail, depending on how the method is invoked. There is nothing guaranteeing that your event handler only gets called with Common.WinLose_ProgressStage that can be inspected without checking your full program. It could be called with a plain EventArgs too: you made that possible by making the parameter type EventArgs.
EventHandler<T> causes more compile-time type checking. If other code attempts to pass in EventArgs.Empty, the call would simply fail to compile.
It's basically the same as "why shouldn't I make all my parameters of type object"? Sure, you could do that. And if you do that, casting back wherever needed, your code would work. But I know I prefer
long Add(long x, long y) { return x + y; }
over
object Add(object x, object y) { return (long)x + (long)y; }
and I suspect that in this case, you do too. Yet this is exactly what you're doing when you make the parameter type EventArgs rather than Common.WinLose_ProgressStage.
Basically what the title says.
Whats the difference between those two (I am currently using the first one)
private EventHandler _progressEvent;
and
private event EventHandler _progressEvent;
I have a method
void Download(string url, EventHandler progressEvent) {
doDownload(url)
this._progressEvent = progressEvent;
}
The doDownload method would call the
_progressEvent(this, new EventArgs());
It works fine, so far. But I feel I am doing something horribly wrong.
The first defines a delegate, the second defines an event. The two are related, but they're typically used very differently.
In general, if you're using EventHandler or EventHandler<T>, this would suggest that you're using an event. The caller (for handling progress) would typically subscribe to the event (not pass in a delegate), and you'd raise the event if you have subscribers.
If you want to use a more functional approach, and pass in a delegate, I would choose a more appropriate delegate to use. In this case, you're not really providing any information in the EventArgs, so perhaps just using System.Action would be more appropriate.
That being said, an event approach appears more appropriate here, from the little code shown. For details on using events, see Events in the C# Programming Guide.
Your code, using events, would likely look something like:
// This might make more sense as a delegate with progress information - ie: percent done?
public event EventHandler ProgressChanged;
public void Download(string url)
{
// ... No delegate here...
When you call your progress, you'd write:
var handler = this.ProgressChanged;
if (handler != null)
handler(this, EventArgs.Empty);
The user of this would write this as:
yourClass.ProgressChanged += myHandler;
yourClass.Download(url);
For private, there is no difference between the two, but for public you would want to use event.
The event keyword is an access modifier like private internal and protected.
It is used for restricting access to multicast delegates. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/event
Going from most visible to least visible we have
public EventHandler _progressEvent;
//can be assigned to from outside the class (using = and multicast using +=)
//can be invoked from outside the class
public event EventHandler _progressEvent;
//can be bound to from outside the class (using +=), but can't be assigned (using =)
//can only be invoked from inside the class
private EventHandler _progressEvent;
//can be bound from inside the class (using = or +=)
//can be invoked inside the class
private event EventHandler _progressEvent;
//Same as private. given event restricts the use of the delegate from outside
// the class - i don't see how private is different to private event
I attached an event handler to Entity Framework's SavingChanges event. Now, I found out I need to attach the same event handler somewhere else in the solution. Both situations (maybe even more if we dig deeper) require the same code so it makes sense to extract to a method and call the same method from multiple event handlers.
The method body includes references to the sender object and eventargs. How do I pass these parameters to the method, even when it's in its own class ?
The sender and event arguments should be part of your method signature and will be passed to the method you are writing when the event is fired. So the variables are defined as parameters to your event handler, and the values for those will be sent by the event trigger.
// I don't know what the proper signature is for a SavingChanges event handler
public class EventHandlers
{
public static void SavingChangesHandler(object sender, EventArgs args)
{
// do something with sender and args here
}
}
// in your other code
SomeObject.SavingChanges += EventHandlers.SavingChangesHandler;
Basically I am attempting to write a generic interprocess communication implementation between C# and the Android platform (using Java).
Creating the socket stack is simple enough but what I am wondering is what would be a good pattern to passing in delegates into my TcpServer class and raising the required events.
The idea so far is.
while (connected) {
//Compile all the required data and so forth
switch (currentState)
{
case CurrentServerState.EventReceived:
//Raise my event...
break;
case CurrentServerState.ObjectReceived:
break;
}
}
So would the correct implementation simply expose an array of delegates and use reflection to match event names or something along those lines? What are my options? Also how do I make sure that any raised events are raised in the UI thread given that this is all occurring from a thread created for the server?
If you don't need to pass any custom arguments to the event handler you can use the default EventHandler delegate which uses the base EventArgs.
Declare the events you want to make available like this:
public event EventHandler EventReceived;
public event EventHandler ObjectReceived;
Declare a protected method for each event to handle raising the event for you. This is really just a convenience to keep from repeating this each time you need it. You could do this inline.
Your events will be null if there are no attached event handlers. The method handles checking for this before firing the event.
protected void RaiseEventReceived(EventArgs e)
{
if (EventReceived != null)
EventReceived(this, e);
}
Then call the method when you want to raise the event. The method will handle checking to see if anyone is listening for the event.
public void SomeOtherMethod()
{
while (IsConnected)
{
switch (CurrentState)
{
case CurrentServerState.EventReceived:
RaiseEventReceived(EventArgs.Empty);
break;
case CurrentServerState.ObjectReceived:
RaiseObjectReceived(EventArgs.Empty);
break;
}
}
}
You can declare your own class to pass custom arguments to the event handlers by deriving from EventArgs such as the following. By convention your class should be named *something*EventArgs.
public class EventReceivedEventArgs : EventArgs
{
// Declare properties to hold additional event info here
}
Then you would need to declare a custom delegate that takes your new event args parameter:
public delegate void EventReceivedEventHandler(object sender, EventReceivedEventArgs e);
Update your event declarations to use your new delegate type instead of EventHandler:
public event EventReceivedEventHandler EventReceived;
And finally, when raising the event you of course would want to create a new instance of your custom event arguments class and intitialize your custom properties.
Clients can attach multiple handlers to your events using the normal syntax and they will always be called on the correct thread.
This seems odd to me -- VB.NET handles the null check implicitly via its RaiseEvent keyword. It seems to raise the amount of boilerplate around events considerably and I don't see what benefit it provides.
I'm sure the language designers had a good reason to do this.. but I'm curious if anyone knows why.
It's certainly a point of annoyance.
When you write code which accesses a field-like event within a class, you're actually accessing the field itself (modulo a few changes in C# 4; let's not go there for the moment).
So, options would be:
Special-case field-like event invocations so that they didn't actually refer to the field directly, but instead added a wrapper
Handle all delegate invocations differently, such that:
Action<string> x = null;
x();
wouldn't throw an exception.
Of course, for non-void delegates (and events) both options raise a problem:
Func<int> x = null;
int y = x();
Should that silently return 0? (The default value of an int.) Or is it actually masking a bug (more likely). It would be somewhat inconsistent to make it silently ignore the fact that you're trying to invoke a null delegate. It would be even odder in this case, which doesn't use C#'s syntactic sugar:
Func<int> x = null;
int y = x.Invoke();
Basically things become tricky and inconsistent with the rest of the language almost whatever you do. I don't like it either, but I'm not sure what a practical but consistent solution might be...
we usually work around this by declaring our events like this:
public event EventHandler<FooEventArgs> Foo = delegate { };
this has two advantages. The first is that we don't have check for null. The second is that we avoid the critical section issue that is omnipresent in typical event firing:
// old, busted code that happens to work most of the time since
// a lot of code never unsubscribes from events
protected virtual void OnFoo(FooEventArgs e)
{
// two threads, first checks for null and succeeds and enters
if (Foo != null) {
// second thread removes event handler now, leaving Foo = null
// first thread resumes and crashes.
Foo(this, e);
}
}
// proper thread-safe code
protected virtual void OnFoo(FooEventArgs e)
{
EventHandler<FooEventArgs> handler = Foo;
if (handler != null)
handler(this, e);
}
But with the automatic initialization of Foo to an empty delegate, there is never any checking necessary and the code is automatically thread-safe, and easier to read to boot:
protected virtual void OnFoo(FooEventArgs e)
{
Foo(this, e); // always good
}
With apologies to Pat Morita in the Karate Kid, "Best way to avoid null is not have one."
As to the why, C# doesn't coddle you as much as VB. Although the event keyword hides most of the implementation details of multicast delegates, it does give you finer control than VB.
You need to consider what code would be required if setting up the plumbing to raise the event in the first place would be expensive (like SystemEvents) or when preparing the event arguments would be expensive (like the Paint event).
The Visual Basic style of event handling doesn't let you postpone the cost of supporting such an event. You cannot override the add/remove accessors to delay putting the expensive plumbing in place. And you cannot discover that there might not be any event handlers subscribed so that burning the cycles to prepare the event arguments is a waste of time.
Not an issue in C#. Classic trade-off between convenience and control.
Extension methods provide a very cool way, to get around this. Consider the following code:
static public class Extensions
{
public static void Raise(this EventHandler handler, object sender)
{
Raise(handler, sender, EventArgs.Empty);
}
public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
if (handler != null) handler(sender, args);
}
public static void Raise<T>(this EventHandler<T> handler, object sender, T args)
where T : EventArgs
{
if (handler != null) handler(sender, args);
}
}
Now you can simply do this:
class Test
{
public event EventHandler SomeEvent;
public void DoSomething()
{
SomeEvent.Raise(this);
}
}
However as others already mentioned, you should be aware of the possible race condition in multi-threaded scenarios.
Don't really know why is this done, but there's a variation of a Null Object pattern specifically for delegates:
private event EventHandler Foo = (sender, args) => {};
This way you can freely invoke Foo without ever checking for null.
Because RaiseEvent carries a some overhead.
There's always a tradeoff between control and ease of use.
VB.Net: ease of use,
C#: more control as VB
C++: even more control, less guidance, easier to shoot yourself in the foot
Edit: As the OP points out, this answer does not address the body of the question. However, some may find it useful because it does provide an answer for the title of the question (when taken by itself):
Why does C# require you to write a null check every time you fire an event?
It also provides context for the intent of the body of the question which some may find useful. So, for those reasons and this advice on Meta, I'll let this answer stand.
Original Text:
In its MSDN article How to: Publish Events that Conform to .NET Framework Guidelines (C# Programming Guide) ( Visual Studio 2013), Microsoft includes the following comment in its example:
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
Here is a larger excerpt from Microsoft's example code that gives context to that comment.
// Wrap event invocations inside a protected virtual method
// to allow derived classes to override the event invocation behavior
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
// Event will be null if there are no subscribers
if (handler != null)
{
// Format the string to send inside the CustomEventArgs parameter
e.Message += String.Format(" at {0}", DateTime.Now.ToString());
// Use the () operator to raise the event.
handler(this, e);
}
}
Note that as of C# 6, the language now provides a concise syntax to perform this null check conveniently. E.g.:
public event EventHandler SomeEvent;
private void M()
{
// raise the event:
SomeEvent?.Invoke(this, EventArgs.Empty);
}
See Null Conditional Operator
The reason really boils down to C# giving you more control. In C# you do not have to do the null check if you so choose. In the following code MyEvent can never be null so why bother doing the check?
public class EventTest
{
private event EventHandler MyEvent = delegate { Console.WriteLine("Hello World"); }
public void Test()
{
MyEvent(this, new EventArgs());
}
}