0

Why C# allows to unsubscribe from the event when the event handler is defined as a function, but not when the event handler is defined as a delegate?

Consider the following code that works:

void SomeFunction()
{
  var eventRaiser = ClassRaisingEvent.GetEventRaiser();

  void handler(object sender, EventArgs ev)
  {
    ProcessData(ev);
    eventRaiser.OnEvent -= handler;
  }

  eventRaiser.OnEvent += handler
  eventRaiser.Process();
}

But this fails to compile at the indicated spot:

void SomeFunction()
{
  var eventRaiser = ClassRaisingEvent.GetEventRaiser();

  DelegateType handler = (object sender, EventArgs ev) =>
  {
    ProcessData(ev);
    eventRaiser.OnEvent -= handler; // FAILS here with "Use of unassigned local variable 'handler '"
  }

  eventRaiser.OnEvent += handler
  eventRaiser.Process();
}

EDIT: This question is not how to unsubscribe. This is why (in technical sense) function name is captured in the scope of the function, but the delegate's isn't.

EDIT2: Answer here (and esp. pt. 2 in the answer) explains the behavior I'm seeing.

jpou
  • 1,935
  • 2
  • 21
  • 30
  • jpou if the question is not about unsubscribing from events, but instead it's about unassigned local variables of type `Delegate`, you should probably present a more general example that's not related to events. Something like an `Action action = () => { action(); };`. As it stands now, I can't vote for your question to be reopened, because it looks awfully similar to the [How to remove a lambda event handler](https://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler). – Theodor Zoulias Aug 01 '21 at 10:09

1 Answers1

1

The local function is defined at compile time, just like other functions. The handler variable, however, is only known at runtime. So, as the compiler tells you, you cannot use the handler variable before it's been assigned a value, which means after the closing } of your delegate.

What you could do to get your second snippet working, is to initialize the variable first:

void SomeFunction()
{
  var eventRaiser = ClassRaisingEvent.GetEventRaiser();

  DelegateType handler = null;
  handler = (object sender, EventArgs ev) =>
  {
    ProcessData(ev);
    eventRaiser.OnEvent -= handler;
  };

  eventRaiser.OnEvent += handler;
  eventRaiser.Process();
}
Xerillio
  • 4,855
  • 1
  • 17
  • 28
  • Your suggested approach also results in "Use of unassigned local variable" error. – jpou Aug 01 '21 at 08:02
  • @jpou Apart from a couple semi-colons I missed before (now fixed in the answer) I don't see the same error - [see here](https://dotnetfiddle.net/F881m6). – Xerillio Aug 01 '21 at 09:37
  • 1
    My bad! Tested with "DelegateType handler;" instead of "DelegateType handler = null;" Your suggestion works perfectly well. – jpou Aug 01 '21 at 14:12