VB.NET to C# with Event Handlers - c#

Hi all sorry but you must get this all the time, I have tried to search for it but could not find anything specific to what I am looking for.
Basically I pretty much know VB.NET fully and I use it constantly, something I want to get into is C# so I have decided to use my free time to try and get a grip on this. I am doing this by using one of my old VB.NET custom binary objects and converting it by hand (not really using a converter as I want to learn it rather than just converting it.) I am however using the internet to guide me. So far I am trying to create custom even handlers my previous VB.NET code was as follows;
Public Event BeforeExecution_Handler()
but doing it in C# seems to be a bit more trickier and i have made the following
public event BeforeExecution_HandlerEvent BeforeExecution_Handler;
public delegate void BeforeExecution_HandlerEvent();
No first is this correct, but secondly what is going on here, why do I have to create definitions for it twice. I am having a guess that the delegate section is where you put variables but why is it like this. Can somebody explain

In VB.NET you can implicitly create a delegate, so you can just do something like this:
Declaration:
Public Event MsgArrivedEvent(ByVal message As String) 'behind the scenes a delegate is created for you
Invocation:
RaiseEvent MsgArrived("foo")
In C# you have to use delegates.
Declaration:
public delegate void MsgArrivedEventHandler(string message);
public event MsgArrivedEventHandler MsgArrivedEvent;
Invocation:
MsgArrivedEvent("Test message");
Note that you can also explicitly create a delegate in VB.NET in the same way as C# but this is just more typing for no gain really:
Declaration:
Public Delegate Sub MsgArrivedEventHandler(ByVal message As String)
Public Event MsgArrivedEvent As MsgArrivedEventHandler
Invocation:
RaiseEvent MsgArrivedEvent("foo")
Also note that best practise is actually to use use a sender and EventArgs class (or a class inherited from it) as the parameters to the Event/Delegate:
public delegate void MsgArrivedEventHandler(object sender, EventArgs e);

Related

Creating events without EventArgs

When creating an event, it is standard to send an EventArgs object as the second argument. However, often times the event may only need to send one piece of data, such as a string or int. As far as I know, you cannot really do anything with the base EventArgs class.
So is it really necessary to create an entire new class with one field just to send a simple string/int with an event?
Example
public delegate void JoinButtonEvent(object sender, string buttonId);
vs
public delegate void JoinButtonEvent(object sender, JoinButtonEventArgs e);
Where JoinButtonEventArgs is a class with field called buttonId.
No it's not necessary for your code to compile; but coding conventions wise its a good idea.
Sure you only care about one variable this time, but if you need another variable in the future you have to update all the old code to have an additional parameter instead of just adding another property to a central class when you need something new. (As events are not polymorphic, and can not be overridden like methods can be, to have different parameters for the same method name)

Event parameter; "sender as Object", or "sender as T"?

When I write public events for my business objects, I've adapted the habit of always passing the instance as "sender as Object", in addition to additional specific parameters. I just asked myself now why am I not specifying the class?
So for you with more experience; Do you ever pass the distinct class as sender in an event? And if so, what are your decision criteria for when this is ok/not ok?
Don't be extreme. EventHandler(object sender, EventArgs e) has an object sender so that we can use it in many circumstances. But it doesn't mean a strongly-typed sender is evil. A strongly-typed sender is useful when this delegate is not going to be widely used(like EventHandler) e.g.
public delegate void SaveHandler(Controller sender, EventArgs e);
Now other developers(or someone using your library) can recogonize that the sender have to be a Controller, and they will be glad not to code like this:
public void MySaveHandler(object sender, EventArgs arg)
{
var controller = sender as Controller;
if (controller != null)
{
//do something
}
else
{
//throw an exception at runtime?
//It can be avoided if sender is strongly-typed
}
}
And you can even make it generic:
public delegate void SaveHandler<T>(T sender, EventArgs args)
where T: IController;
It's pure legal and good practice in C#. You should make clear what you want to do, and then choose the better way. Either of them is evil/bad.
There is a design guideline that specified that an event-handler should have two params: sender (an Object) and e (EventArgs or derived from that).
There no such restriction. It is just a guideline that is followed throughout BCL (Base Class Library) and other popular frameworks.
I would recommend you follow it to keep it consistent if it is going to be used by other developers or be released as a framework.
As far as I see it you can either create delegates with the parameters you want and then create an event using that delegate and then you can call the event and pass the parameters in or you can use Custom Event Argument as shown here. As the other answer suggests. Keep it consistent.
Doesn't really answer your question about the decision criteria but hope it helps
My current philosophy is to keep code practices as close to the standard Microsoft way as possible. You get two things from this:
New developers can quickly understand your code
You train existing developers how the rest of the framework works
It is good practice to use the object sender, EventArgs e signature, as the method can handle any events of that signature. For example, in a project using a charting control, there are several types of MouseOver events - from a DataSeries, from the Legend, from the whole Canvas.
That way, you can handle any source of the event, as at most times, the information is in the EventArgs.
Also, you don't have to cast the sender when passing it to the delegate, as any class instance is an object deep down.
There was a lot of discussion on a related question on StackOverflow some time ago. Here is that question: Event Signature in .NET -- Using a strong-typed sender
Eventually, it comes down to preference. In most cases, you'd like your event handlers to be bound to a particular type of class so making the sender an object and then casting back to the class in order to get access to its properties might not go down well with you [it doesn't go down well for me either].
Besides, with .NET 3+ and the introduction of delegate covariance and contravariance, it should not be a problem to use a strongly typed delegate. I must admit, I've used strongly typed event handlers more than once in my code.
Like I said earlier, it comes down to preference; Microsoft just issued a set of guidelines not rules...
It is not a binding on you to have such implementation. Its usually done because of the EventHandler delegate was designed with such prototype.
Its a simple guideline followed through Base Class Library. But sure you can make you own Parameters and implementations.
But remember if it is to be used by some developer other that you, he will need to know about such implementation. Its don for greater good and flexibility to use an event anywhere irrespective of class its used in.
If you define a Custom Prototype for event then i would suggest that you also define Custom Delegate that will ensure you will have catch an exception if proper type is not passed. (User will need to do an Explicit cast if required)
Like this:
public delegate void MyEventHandler( MyType sender, EventArgs e);
Then use it where required as:
this.MyEvent += new MyEventHandler(my_eventhandlerfunction);

What controls where an event can be called?

Say I have a class like this:
public class FauxIdentityForm
{
public Guid FormID { get; set; }
public event EventHandler Closed;
public void TheObjectWasClosed(EventArgs e)
{
Closed(this, e);
}
}
It is fine for me to call the Closed Event inside the TheObjectWasClosed method. But if, in a different class (even in the same file), I have a method like this:
public void CallTheEvent()
{
FauxIdentityForm _formIdentity = new FauxIdentityForm {FormID = Guid.NewGuid()};
_formIdentity.Closed(_formIdentity, null); // <-- Does not compile!
}
The call to Closed is shot down by the compiler (it wants me to only use += and -=).
So, is actually calling the event only allowed inside the class? Is that the limitation?
If so, is there anyway around it? And if not, why did the creators of C# do this? (It makes working with events very hard sometimes. I imagine there is a good reason and it is probably saving me from myself, but I would like to know it.)
It's complicated :)
What you're using is called a field-like event. When you declare one of those in your class, you're creating a field and an event. When you "call the event" you're actually invoking the delegate referred to by the field. As it's a private field, you have access to it within the class (and any nested types), but not outside.
Events themselves in C# only support add and remove operations. From the outside, callers can only subscribe to an event and unsubscribe from it. They can't raise it, or find out anything about who's subscribed. Of course, the class can provide a method which will raise the event, but the other class can't access the backing field for the event
I've written this up in more detail in an article about events and delegates.
In fact, Closed(this, e); is nothing but calling invoke on a private delegate. This is why only the class can call it.
C# hides all the complexity from you and it creates a private delegate of type event for you (you can use ILDASM to see all this).
This is private so it is not even protected. This is why it is recommended to use a protected method to raise the event so the subclasses could have access to the event.
So, is actually calling the event only allowed inside the class? Is that the limitation?
Yes
If so, is there anyway around it?
Only with the consent (help) from the FauxIdentityForm class. It could have a public OnClosed() method.
An Event is a lot like a property, one of its main purposes is encapsulation and that is what you ran into.

Benefits of events using EventArgs/EventArgs<T> delegate types instead of…

I understand the benefits of events using delegate types with signature delegate void delegate_name(object sender, EventArgs e)
a) But besides the fact that it may save us some typing, are there any other reasons why we should use already defined delegate types EventHandler/EventHandler<T> instead of declaring our own delegate types with signature delegate void delegate_name(object sender, EventArgs e)?
b) Two other reason I can think of for using the predefined delegate types EventArgs/EventArgs<T> are:
people consuming particular event ( say event EventHandler my_event ) will immediately know how to use that event?
perhaps some popular third party methods accept as parameters EventHandler/ EventHandler<T> delegate types, and thus if there’s any chance that our code may use those third party methods, we should use predefined delegates EventHandler/Eventhandler<T>?
thank you
To me, the question is a little strange. What would be the benefit of doing this otherwise (defining delegate types that exactly match EventHandler<TEventArgs> for some TEventArgs)?
That said, there is at least one benefit I can think of to doing it the "normal" way: certain APIs already expect to deal with EventHandler<TEventArgs> delegates; for example, Rx Extensions includes a method that looks like this:
Observable.FromEvent<TEventArgs>(
Action<EventHandler<TEventArgs>> addHandler,
Action<EventHandler<TEventArgs>> removeHandler
);
If you defined your own delegate, using methods like this -- which expect EventHandler<TEventArgs> delegates -- would become more complicated than necessary for no added benefit (that I can see, anyway).
You forgot an important one:
the lunatic that will maintain your code some day will find out where you live and hurt you.
You've answered your own question:
Syntactical Sugar (less to write) to maintain the convention
Interoperability (using the EventHandler type let's you easily integrate events from other libraries
In short; there's no good reason not to use it unless you're forced to (which typically is the result of people not being aware of it, or not understanding it).
From Pro C# 2008 and the .NET 3.5 Platform:
When the compiler processes the event keyword, you are automatically provided
with registration and unregistration methods* as well as any necessary member
variables** for your delegate types. ...To be sure, the event keyword is
little more than syntactic sugar in that it simply saves you some typing time.
* This includes overloading the handy += and -= operators.
** ...which are already marked private so they can't end-run.
When you use the generic EventHandler delegate, you don't even have to write out your custom delegate type at all.
I'm going to rock the boat here and propose something entirely heretical. I used to be firmly in the EventArgs camp because I clung to the "MS recommends this and it's always been done this way" mentality, but over time I came to hate EventArgs. Why?
It promotes a .NET-1.0ish style of coding which relies upon weak-typing/type casting and makes me feel unclean.
It forces your class which implements the event to pollute the heap with new EventArg instances every time it fires, which also makes me uneasy. Why not have my events give subscribers exactly what they need instead of wrapping it up in an extra class that does nothing for me.
The signatures of your callback methods which subscribe to the event look like garbage and have very little semantic detail - e.g. object sender - WHAT is sender?!?!
What I do now is declare my own event handler delegates, which I store neatly in their own "Delegates" folder in my solution as well as their own namespace. So my delegate may reside in its own file like this:
namespace MyAPI.Data.Delegates
{
public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data);
}
The event declaration now looks like this:
public event DataEventHandler<TData> DataReady = delegate { };
Benefits to this approach:
Method signatures have more semantic detail. You know WHO is sending WHAT.
Strong-typing is preserved. No more casting object sender to what you think it should be.
You don't have to new() up objects and pollute the heap, which can be problematic if your event fires frequently. Just pass your subscribers exactly what they need, whether it be an object reference or a value type.
By using the ___EventHandler naming convention for your delegates, you are still promoting a uniform style for your code which makes it easy for users of your API to know what your intent is.
The only "drawback" is that it makes it hard for users of your code to wire up your event to existing methods which have the object sender, EventArgs e signature. However, this point is moot because if your event delivers any extra data (e.g. you created your own EventArgs subclass) then they'll have to change the method signature anyway (or cast to your subclass type). Either way, that's still nasty.
That's why I like my way.

C# Action/Delegate Style Question

What is considered better style for an event definition:
public event Action<object, double> OnNumberChanged;
or
public delegate void DNumberChanged(object sender, double number);
public event DNumberChanged OnNumberChanged;
The first takes less typing, but the delegate one gives names to the parameters. As I type this, I think number 2 is the winner, but I could be wrong.
Edit: A different (third) approach is the winner. Read below.
Neither 1 or 2. A third option is the winner
public event EventHandler<NumberChangedEventArgs> NumberChanged;
You're breaking a number of style guidelines for developing in C#, such as using a type for event args that doesn't extend EventArgs.
Yes, you can do it this way, as the compiler doesn't care. However, people reading your code will do a WTF.
Don't create a new type if you don't have to. I think this is better:
public event Action<object, double> OnNumberChanged;
The reason that the Action and Func delegate families exist is to serve this very purpose and reduce the need for new delegate type creation by developers.
Typically I stick to using an EventArgs derived class as the argument. It makes the code much more consistent.
I have a class:
public class ApplyClickedEventArgs : EventArgs
{
...
}
and a handler:
void cpy_ApplyClicked(object sender, ApplyClickedEventArgs e)
{
...
}
The declaration is:
public event EventHandler<ApplyClickedEventArgs> ApplyClicked;
As with all questions about coding style. Pick the one you prefer, or that your team prefers, and keep it consistent throughout the project. As long as everyone who needs to can read it efficiently you will be fine.
I think option 1 is better if I were to choose, but IIRC, the official guidelines for events state that your second parameter has to be a class with the name XxxEventArgs, and should have EventArgs up in its inheritance chain.

Categories

Resources