6

Why does this declaration+assignment cause an error:

// Use of unassigned local variable 'handler'.
SessionEndingEventHandler handler = (sender, e) => { isShuttingDown = true; SystemEvents.SessionEnding -= handler; };

while this does not:

SessionEndingEventHandler handler = null;
handler = (sender, e) => { isShuttingDown = true; SystemEvents.SessionEnding -= handler; };

In is intuitive that the first statement should cause an error but not immediately clear why the second one is not.

Furthermore, how could I tell if the SystemEvents.SessionEnding event has been actually unsubscribed after the call to handler(null, null)? The GetInvocationList only works with delegates.

SystemEvents.SessionEnding += handler;
handler(null, null);
Raheel Khan
  • 14,205
  • 13
  • 80
  • 168
  • 2
    The first statement is more equivalent to `SessionEndingEventHandler handler;`, whereas in the second statement you assign it to null. Its unassigned until the lambda is fully constructed. See http://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler – Ron Beyer Oct 11 '15 at 01:32

1 Answers1

10

It's for the same reason that you'd expect this to fail:

int i = 1 - i;

The right-hand side of the statement is evaluated before the assignment, and at the time when it's evaluated, the variable hasn't been assigned yet.

In case you think lambdas/delegates change things, consider the following statement:

int i = ((Action)() => 1 - i)();

Because you're creating the lambda before i is assigned, it's possible that i could be used before any value has been assigned to it. The fact that you don't expect that to happen in your case doesn't change things from the compiler's perspective--you have to explicitly assign a value to the variable before it's used. If it's a null value, then at least the compiler knows you're considering the possibility that it's going to be null when you get to it.

Regarding your final question, a SessionEndingEventHandler is a delegate. So this would work fine:

var unsubscribed = SystemEvents.SessionEnding == null ||
    !SystemEvents.SessionEnding.GetInvocationList().Contains(handler);
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315