Как отписаться от анонимной функции в методе Dispose класса?

У меня есть класс A... в его конструкторе... я назначаю анонимную функцию обработчику событий Object_B.

Как удалить (отписаться) это из метода Dispose класса A?

Любая помощь будет оценена! Спасибо

Public Class A
{

public A()
 {

 B_Object.DataLoaded += (sender, e) =>
                {
                   Line 1
                   Line 2
                   Line 3
                   Line 4
                };
 }

Public override void Dispose()
{
  // How do I unsubscribe the above subscribed anonymous function ?
}
}

person Relativity    schedule 16.03.2012    source источник
comment
Что такое B_Object? Является ли это переменной-членом класса A? И доступен ли он где-либо за пределами A; могут ли у него быть другие слушатели?   -  person Dax Fohl    schedule 17.03.2012
comment
возможный дубликат анонимного метода отмены подписки в C#   -  person Tim Schmelter    schedule 17.03.2012
comment
да, это член... какой экземпляр класса B   -  person Relativity    schedule 17.03.2012


Ответы (3)


Вы не можете, в принципе. Либо переместите его в метод, либо используйте переменную-член, чтобы сохранить делегат на потом:

public class A : IDisposable
{
    private readonly EventHandler handler;

    public A()
    {
        handler = (sender, e) =>
        {
           Line 1
           Line 2
           Line 3
           Line 4
        };

        B_Object.DataLoaded += handler;
     }

     public override void Dispose()
     {
        B_Object.DataLoaded -= handler;
     }
}
person Jon Skeet    schedule 16.03.2012
comment
Итак, если мы не отписались от этого... это, очевидно, приведет к утечке памяти, верно? - person Relativity; 17.03.2012
comment
@Relativity: Не обязательно. На самом деле вы не говорили о B_Object.DataLoaded - если это на самом деле событие экземпляра, а не статическое событие, то, если объект собран, подписка на событие больше не будет иметь значения. Все зависит от контекста... - person Jon Skeet; 17.03.2012
comment
B_Object.DataLoaded — это событие экземпляра, а не статическое событие. Не могли бы вы уточнить это: - если объект собран, подписка на событие не имеет значения - person Relativity; 17.03.2012
comment
@Relativity: если объект X подписывается на какие-либо события от объекта Y, но не отменяет подписку, висячие события заставят объект X оставаться в памяти, по крайней мере, до тех пор, пока объект Y. Если время жизни объекта Y в памяти будет намного дольше, чем полезное время жизни объекта X, это может быть плохо. Если в течение жизни памяти объекта Y будет создано и заброшено много экземпляров объекта X, это может быть очень плохо, если не катастрофично. Если, однако, Y будет иметь право на сбор, когда время X станет бесполезным, оборванная подписка не будет поддерживать жизнь X. - person supercat; 19.03.2012
comment
@Relativity: Несмотря на то, что оборванные подписки в таких случаях безвредны, они все равно неприятны. Меня очень раздражает, что ни vb.net, ни C# не предоставляют удобных средств для отмены подписки на все события, к которым они привязаны. - person supercat; 19.03.2012

Правильный способ сделать это — использовать Rx Extensions. Иди смотри видео здесь:

http://msdn.microsoft.com/en-us/data/gg577611

Я нашел фильм "блюз" особенно полезным.

person Brannon    schedule 16.03.2012

Это альтернатива без использования переменной обработчика.

Public Class A
{

 public A()
  {

    B_Object.DataLoaded += (sender, e) =>
                {
                   Line 1
                   Line 2
                   Line 3
                   Line 4
                };
  }

  Public override void Dispose()
  {
   if(B_Object.DataLoaded != null)
   {
     B_Object.DataLoaded -=
         (YourDelegateType)B_Object.DataLoaded.GetInvocationList().Last();
       //if you are not sure that the last method is yours than you can keep an index
       //which is set in your ctor ...
   }
  }
 }
person Ion Sapoval    schedule 16.03.2012