EventHandler<T> and EventHandler - c#

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.

Related

Simplest way to handle creating events in a class

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.

Proper usage of EventArgs

I have a pretty basic event:
public event EventHandler OnAborted;
All I need to do is call this event, I don't even need to provide any arguments, so it's nothing fancy. I'm confused with the correct usage of the EventArgs argument.
I can use:
if (OnAborted != null)
OnAborted(this, EventArgs.Empty);
Or I can even use:
if (OnAborted != null)
OnAborted(this, new EventArgs());
In both cases, EventArgs seems to be pretty useless, I can't even provide any arguments (not that I need to, but that's not the point).
What is the proper usage of EventArgs? Should I create a custom class that inherits EventArgs?
Using EventArgs.Empty does not create a new object and allocates it on the heap. More over, EventArgs.Empty is an instance of the Null Object Pattern. Having an object representing "no value" to avoid checking for null when using it.
To add more to when you should use EventArgs or your proper class, here you have some MSDN guideline on Event Design :
Consider using a derived class of System.EventArgs as the event argument, unless you are absolutely sure the event will never need to carry any data to the event-handling method, in which case you can use the System.EventArgs type directly.
If you define an event that takes an EventArgs instance instead of a derived class that you define, you cannot add data to the event in later versions. For that reason, it is preferable to create an empty derived class of EventArgs. This allows you add data to the event in later versions without introducing breaking changes.

Difference between private EventHandler and private event EventHandler?

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

Action<T> is different event Action<T>?

public class TestA
{
public event Action<int> updateEvent;
...
if(updateEvent != null)
{
Actin<int> tempEvent = updateEvent;
updateEvent(1);
}
}
public class TestB
{
public Action<int> updateEvent;
...
if(updateEvent != null)
{
Actin<int> tempEvent = updateEvent;
updateEvent(1);
}
}
however event Action<T> is eventQueue au
use same and resutl same. What is more good? (i like TestB. Because simple using.)
The event modifier is useful to prevent an assignment. What does it mean? If that's a callback with many handlers attached you may want to prevent that someone simply write:
myObject.UpdateEvent = null or something like that. With event they can't do that. Take a look at Learning C# 3.0: Master the fundamentals of C# 3.0.
The code you use to call the event isn't bad but not so useful, if you assign the delegate to temporary variable you may want to be somehow thread-safe (someone could unhook after your null check) so you should do it before the check:
Action<int> tempEvent = updateEvent;
if (tempEvent != null)
tempEvent(1);
A little side note: if you use events you may want to follow .NET Framework patterns and guidelines, take a look at MSDN
To the compiler, the difference is that the event cannot be invoked except by the declaring class (like a private member). You can use either in the same way.
To design, events should represent their namesake, i.e. events. Think of a Delegate as just the type or signature of methods. You would declare a class to have an event (of type Action), and you would add (subscribe) to that event other Actions (or methods that can be cast to an Action).
Furthermore, it is common practice to create events of a type that inherits from EventHandler<T>
An event is just a delegate with some access wrappers.
The problem with your TestB is that because the updateEvent delegate is public, ANYONE can fire the delegate, not just the class owning it.
Defining it as an Event as in your TestA, client code can only subscribe or unsubscribe to the event, they cannot fire it.
ps. You do not need your tempEvent delegates.

Why does C# require you to write a null check every time you fire an event?

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());
}
}

Categories