Как отменить регистрацию моего обратного вызова Lambda? - PullRequest
5 голосов
/ 27 апреля 2011

Если я создам лямбда-колбэк, такой как этот:

var someInstance = new SomeObject();

someInstance.Finished += (obj, args) =>
{
      // Do something

      // Deregister here
};

someInstance.DoAction();

Как я могу отменить регистрацию обратного вызова как часть фактического кода обработчика? Этот образец был бы идеальным, поскольку я мог гарантировать, что он выпущен как можно скорее.

Я видел похожие вопросы, но не тот, в котором этот тип примеров рассматривается напрямую.

Ответы [ 5 ]

6 голосов
/ 27 апреля 2011

С чем-то вроде

var someInstance = new SomeObject();

EventHandler myDelegate = null;
myDelegate = (obj, args) =>
{
      // Do something

      // Deregister here
      someInstance.Finished -= myDelegate;
};
someInstance.Finished += myDelegate;

someInstance.DoAction();
5 голосов
/ 27 апреля 2011

Вы можете использовать MethodInfo.GetCurrentMethod внутри своей лямбды, чтобы получить MethodInfo лямбды.

С MethodInfo вы можете использовать Delegate.CreateDelegate, чтобы получить правильно набранного делегата, представляющего вашу лямбду.

И с помощью делегата вы можете отменить регистрацию лямбда-выражения, не сохраняя свою функцию в переменной или не называя ее именованным методом.

class MyClass 
{
    public event EventHandler TheEvent;

    void TestIt()
    {
        TheEvent += (sender, eventargs) => 
            {
            Console.WriteLine("Handled!"); // do something in the handler

            // get a delegate representing this anonymous function we are in
            var fn = (EventHandler)Delegate.CreateDelegate(
                             typeof(EventHandler), sender, 
                             (MethodInfo)MethodInfo.GetCurrentMethod());

            // unregister this lambda when it is run
            TheEvent -= fn;
        };


        // first time around this will output a line to the console
        TheEvent(this, EventArgs.Empty);

        // second time around there are no handlers attached and it will throw a NullReferenceException
        TheEvent(this, EventArgs.Empty);
    }

}
5 голосов
/ 27 апреля 2011

Если вы хотите отменить регистрацию, то лучше определить вашу лямбду как Действие, так что вы можете написать:

someInstance.Finished += MyCustomAction;

и позже

someInstance.Finished -= MyCustomAction;
1 голос
/ 27 апреля 2011

Похоже, это работает:

EventHandler handler = null;
handler = new EventHandler((sender, e) => SomethingHappened -= handler);
SomethingHappened += handler;

Просто убедитесь, что вы не назначаете handler какому-либо другому значению, так как замыкание связано с этой переменной.На это и жалуется Resharper как «Доступ к измененному закрытию».

1 голос
/ 27 апреля 2011

Если вы хотите впоследствии удалить обработчик событий, вы должны использовать именованную функцию:

  someInstance.Finished += HandleFinished;

  //...
  void HandleFinished(object sender, EventArgs args) 
  {  
    someInstance.Finished -= HandleFinished;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...