One of the niceties included with C# 3.0 is lambda expressions, a concise syntax for implementing anonymous methods. Lambda expressions can be over-used, but they're very handy for certain kinds of things, like defining how asynchronous callbacks should be handled, all within a single method.
Lambda expressions are also very handy for implementing event handlers. For instance, if you've got an AlarmClock class that looks like this:
class
AlarmClock
You would normally assign and implement an event-handler like this, with a separate defined method:
class
Program
But with lambda expressions, you can do it like this, all in one method:
class
Program
Most folks would agree that this looks cleaner, and is easier to follow. (At least, once you get the hang of lambda expressions, which admittedly have a rather odd syntax.)
The one time this doesn't work is when you need to be able to clear event handlers as well as assign them. The way that you normally do this is so:
public
static
void Main()
But you can't do that with the lambda expression I used above, because you don't have any way to identify the lambda expression that you want to remove. I've seen a variety of folks asking questions about how to clear event handlers implemented as lambda expressions for this very reason.
It turns out that there are (at least) two ways to do it.
class
AlarmClock
public
static
void Main() The syntax for #2 is a bit unwieldy, but it can let you do things that would be difficult or complicated if you had to use a second method. For instance, within lambda expressions you can use local variables declared at the level of the containing function:
public
static
void Main()
To duplicate this without lambda expressions, you'd have to declare the resetEvent and alarmSounded variables at the class level, which isn't nearly as clean, and could lead to some odd bugs if other methods were trying to use those same variables simultaneously.
{
public
event
EventHandler<EventArgs> Alarm;
public
void SoundAlarm()
{
if (Alarm != null)
{
Alarm(this, new
EventArgs());
}
}
}
{
public
static
void Main()
{
AlarmClock clock = new
AlarmClock();
clock.Alarm += new
EventHandler<EventArgs>(clock_Alarm);
clock.SoundAlarm();
}
static
void clock_Alarm(object sender, EventArgs e)
{
Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
}
}
{
public
static
void Main()
{
AlarmClock clock = new
AlarmClock();
clock.Alarm += (s, e) =>
Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
clock.SoundAlarm();
}
}
{
AlarmClock clock = new
AlarmClock();
clock.Alarm += new
EventHandler<EventArgs>(clock_Alarm);
clock.SoundAlarm();
clock.Alarm -= new
EventHandler<EventArgs>(clock_Alarm);
}
{
public
event
EventHandler<EventArgs> Alarm;
public
void SoundAlarm()
{
if (Alarm != null)
{
Alarm(this, new
EventArgs());
}
}
public
void ClearEventHandlers()
{
Alarm = null;
}
}
{
AlarmClock clock = new
AlarmClock();
EventHandler<EventArgs> handleAlarm = null;
handleAlarm = (s, e) =>
{
clock.Alarm -= handleAlarm;
Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
};
clock.Alarm += handleAlarm;
clock.SoundAlarm();
}
Note that you need to assign the handleAlarm variable to null first, because otherwise the compiler complains about the first line of the lambda expression: it thinks that you're trying to muck about with an uninitialized variable. This is only sort of true, but to work around it, just assign the variable to null when you declare it.
{
AlarmClock clock = new
AlarmClock();
EventHandler<EventArgs> handleAlarm = null;
ManualResetEvent resetEvent = new
ManualResetEvent(false);
bool alarmSounded = false;
handleAlarm = (s, e) =>
{
clock.Alarm -= handleAlarm;
Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
alarmSounded = true;
resetEvent.Set();
};
clock.Alarm += handleAlarm;
clock.SoundAlarm();
resetEvent.WaitOne(5000);
if (!alarmSounded)
{
Console.WriteLine("The alarm didn't sound within the timeout period.");
}
}
Infant Baptism and Church History
5 hours ago

|