Using lambda expressions for event handlers - c#

I currently have a page which is declared as follows:
public partial class MyPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//snip
MyButton.Click += (o, i) =>
{
//snip
}
}
}
I've only recently moved to .NET 3.5 from 1.1, so I'm used to writing event handlers outside of the Page_Load. My question is; are there any performance drawbacks or pitfalls I should watch out for when using the lambda method for this? I prefer it, as it's certainly more concise, but I do not want to sacrifice performance to use it. Thanks.

There are no performance implications since the compiler will translate your lambda expression into an equivalent delegate. Lambda expressions are nothing more than a language feature that the compiler translates into the exact same code that you are used to working with.
The compiler will convert the code you have to something like this:
public partial class MyPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//snip
MyButton.Click += new EventHandler(delegate (Object o, EventArgs a)
{
//snip
});
}
}

Performance-wise it's the same as a named method. The big problem is when you do the following:
MyButton.Click -= (o, i) =>
{
//snip
}
It will probably try to remove a different lambda, leaving the original one there. So the lesson is that it's fine unless you also want to be able to remove the handler.

EventHandler handler = (s, e) => MessageBox.Show("Woho");
button.Click += handler;
button.Click -= handler;

No performance implications that I'm aware of or have ever run into, as far as I know its just "syntactic sugar" and compiles down to the same thing as using delegate syntax, etc.

Related

call event with parameters from another event , both different namespace

I would like to call an event having parameters from another event, both have different namespaces, is it passable to do this?
public void event1(object1 sender, eventArgs e1)
{
// code goes here
}
public void event2(object2 sender, eventArgs e2)
{
// here I want call event1 with parametersenter code here
}
is it possible?
The best way to do this is not in terms of events being called but just methods being called.
If in the simplest terms your events just called Method1 and Method2 respectively then you could easily have Method1 call Method2 and do whatever it does.
You could raise potentially raise event1 from inside event2 but it doesn't necessarily make sense to do so (for example if it is a click event it should only be raised by a click. It is best to just refactor common code into a method that can be easily called using standard OOP techniques. In my code below I've made the extracted methods static methods so they are easier to call from other objects and assumed that Method1 is in Class1 (not explicitly shown) which is in Namespace1. You may need to do things slightly differently if you need them to be non-static methods.
Here's the example of what I mean.
public void event1(object1 sender, eventArgs e1)
{
var myParameter = ...;
Method1(myParameter);
}
public static void Method1(object myParameter)
{
// code goes here
}
public void event2(object2 sender, eventArgs e2)
{
var myParameter = ...;
Method2(myParameter);
}
public static void Method2(object myParameter)
{
Namespace1.Class1.Method1(myParameter);
}
Using "MyNameSpace";
thats all you need.
I need to write 30 characters so
include "mynamespace" for c++.
Unless i misunderstood what you meant.

Can I cast event args inside the called function in C# instead of defining delegates?

I have an event:
public event RoutedEventHandler ActionEvent;
I have a superclass:
internal class MyEventArgs : RoutedEventArgs
{
public enum SomeAction
{
ACTION1,
ACTION2,
ACTION3
}
public MyEvent(SomeAction action)
{
this.action = action;
}
public SomeAction action;
}
I call the function:
private void onAction(object sender, MyEventArgs args) { if (ActionEvent != null) ActionEvent(sender, args); }
And finally, hence my question, I cast inside the called method:
void ActionEvent(object sender, RoutedEventArgs e)
{
MyEvent args = (MyEvent)e;
}
Is this legal? Can I avoid introducing delegates? It compiles and runs happily in debug mode.
(I'm new in C#. I have been using C++ for ages. The answer would be a definite yes in C++, but I want to double check that I can do this in C# as well without introducing "hidden" stability problems, multi-threading problems or anything like that. In fact, C# should warn me in real-time if I used a wrong cast, but just I asked just to double check.)
You can do this - but then you're really being very specific in your implementation, without being specific in the type system.
Why not just use EventHandler<TEventArgs>?
public event EventHandler<MyEventArgs> ActionEvent;
Then:
void ActionEvent(object sender, MyEventArgs e)
{
...
}

Hooking a C# event from C++/CLI

So I have a C# class that has the following event:
public class CSClient
{
public delegate void OnMessageHandler(Object sender, EventArgs e);
public event OnMessageHandler OnOptionsEvent;
}
Then I have a C++/CLI class, for which I want to subscribe to OnOptionsEvent.
I have tried something like this:
void CSClientWrapper::Start()
{
GCHandle h = GCHandle::FromIntPtr(IntPtr(_impl));
CSClient^ obj = safe_cast<CSClient^>(h.Target);
__hook(&CSClient::OnOptionsEvent, obj, &CSClientWrapper::OnOptions);
}
void CSClientWrapper::OnOptions(Object^ sender, EventArgs^ args)
{
}
error C2039: 'add_OnOptionsEvent' : is not a member of 'CSClient'
error C2750: 'CSClient::OnMessageHandler' : cannot use 'new' on the
reference type; use 'gcnew' instead
I am completely new to C++CLI, so I suspect it is something really fundamental that I'm missing.
Yes, that's not appropriate syntax. Best to forget that the __hook keyword exists, it was a fairly mistaken idea to add event handling syntax to native C++. You need to create a managed delegate to subscribe the event, correct syntax should be close to:
CSClient^ obj = safe_cast<CSClient^>(h.Target);
obj->OnOptionsEvent +=
gcnew CSClient::OnMessageHandler(this, &CSClientWrapper::OnOptions);

Use of the event keyword in c#

I was wondering what the exact use of events is in c#. I am still in the process of learning c# so I maybe missing something but is it possible to just use delegates.
In this example I wrote a class with a method that counts from 0 to 2^64 and every time it reaches a multiple of a thousand raises an event. Here is the code:
namespace EventDelegate
{
class Program
{
static void Main(string[] args)
{
EventRaiserClass _eventraiser = new EventRaiserClass();
_eventraiser.handler = SomeEventHandler;
_eventraiser.handler += AnotherEventHandler;
_eventraiser.Loop();
Console.Read();
}
static void SomeEventHandler(object sender, EventArgs args)
{
Console.WriteLine("Event raised");
}
static void AnotherEventHandler(object sendr, EventArgs args)
{
Console.WriteLine("Event raised (Another handler)");
}
}
public delegate void Handler(object sender, EventArgs args);
class EventRaiserClass
{
public Handler handler;
public void Loop()
{
for (long i = 0; i < Int64.MaxValue; i++)
{
if ((i % 1000) == 0)
{
EventArgs args = new EventArgs();
RaiseEvent(args);
System.Threading.Thread.Sleep(1000);
}
}
}
private void RaiseEvent(EventArgs args)
{
if (handler != null)
handler(this, args);
}
}
}
What would the difference have been if I had declared the handler delegate variable to be an event like this public event Handler handler.
Sorry if I am been a bit vague or missing something obvious, but I am just wondering if something else happens behind the scenes when using event rather just using delegates or if it's just for readability purposes.
Events and delegates are similar, but events are more restricted, for good reasons.
In your code, you could do all kinds of things with _eventraiser.handler from the outside. You aren't supposed to do most of those things though.
Consider this line:
_eventraiser.handler = SomeEventHandler;
If you use delegates, you would have to check every time you try to attach an event handler if the delegate is null, and then initialize it with =, and if it is not null, you just have to add handlers with +=. If you forget an initialization, you get a null reference exception, if you put in one too many, you will overwrite all the previous things.
If you use events instead of delegates in this example, you don't have to do any of this, and, in fact, you can't even do it. With delegates you could even take it and then pass it around to some other classes, which could potentially be very dangerous.
The same goes for Invoke, and all the other things you can do with a delegate: They aren't there for events. The only things you can do with an event from an outside class is += and -=, that's it. You can view them as delegates with a special public interface with complicated getters and setters.
(Events also have a special add and remove syntax, but that's a rather uncommonly used feature)

Why aren't .NET web control event handlers generic?

I've been wondering this for a while now; but especially more so since I've been more focused on front-end development for the last few weeks. It might sound like a broad question, but hopefully there's an answer, or a reason as to:
Why aren't .NET web control event handlers generic?
Reasoning
The reason I ask, is due to the nicety and elegance of strongly typed event handlers. Throughout my project, wherever required, I tend to use the .NET generic EventHandler<T> delegate, which has been around since .NET 2.0; as discussed here.
public delegate void EventHandler<TArgs>(object sender, TArgs args) where TArgs : EventArgs
It would be relatively straight forward to expand on this, and to define a type for the sender as well, something like so.
public delegate void EventHandler<TSender, TArgs>(TSender sender, TArgs args) where TArgs : EventArgs
Whenever working with .NET controls, occassionally I find myself binding the event handler in the code-behind rather than the ASPX file, and then having to cast the object to the desired type if I need to do any additional checks or alterations.
Existing
Definition
public class Button : WebControl, IButtonControl, IPostBackEventHandler
{
public event EventHandler Click;
}
Implementation
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.MyButton.Click += new EventHandler(MyButton_Click);
}
protected void MyButton_Click(object sender, EventArgs e)
{
// type cast and do whatever we need to do...
Button myButton = sender as Button;
}
Generic
Definition
public class Button : WebControl, IButtonControl, IPostBackEventHandler
{
public event EventHandler<Button, EventArgs> Click;
}
Implementation
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.MyButton.Click += new EventHandler(MyButton_Click);
}
protected void MyButton_Click(Button sender, EventArgs e)
{
// no need to type cast, yay!
}
I know it's a relatively small change, but surely it's more elegant? :)
Because it's old.
The web controls were developed for .NET 1.0, and generics didn't arrive until .NET 2.0.
Of course the controls could have been changed, but that means that all old code would need to be changed to compile (and they would need to be recompiled as the old binaries wouldn't work any more), and all old examples (millions of web pages) would be obsolete.

Categories