Что происходит с обработчиками событий, когда объект выходит из области видимости? - PullRequest
4 голосов
/ 06 июля 2011

Допустим, у нас есть следующие настройки:

public class ClassA
{
   public event EventHandler SomeEvent;
}

public class ClassB : IDisposable
{
   public void SomeMethod(ClassA value)
   {
      value.SomeEvent += (s, e) => { DoSomething(); };
   }

   void DoSomething() { }

   void Dispose() { }
}

public static class Program
{
   static void Main()
   {
      var a = new ClassA();

      using (var b = new ClassB())
         b.SomeMethod(a);

      // POINT OF QUESTION!!
   }
}

Что происходит, когда событие SomeEvent возникает после «ТОЧКИ ВОПРОСА»?

Ответы [ 4 ]

8 голосов
/ 06 июля 2011

Будет вызывать метод удаленного объекта.Вот почему важно отписаться.Это даже может привести к утечке памяти.

1 голос
/ 06 июля 2011

Ничто из вышеперечисленного не отцепит ваш обработчик событий.Поскольку и a, и b выходят из области видимости одновременно, вы будете в безопасности.Поскольку a и b могут быть собраны, то a не сохранит b в живых.

Если вы подняли событие ClassA.SomeEvent после оператора using, то ClassB.DoSomethingбудет вызван, даже если b был удален.В этом случае вам придется явно удалить обработчик событий.

Если бы вы сохранили ссылку на a где-то в другом месте, то b будет поддерживаться a.Опять же, потому что обработчик событий не был удален.

1 голос
/ 06 июля 2011

Вы должны использовать Dispose() метод ClassB, чтобы отписаться от события ClassA.Вы рискуете, что классы не будут собирать мусор, что, конечно, может привести к утечке памяти.Вы должны всегда отписаться от событий.

0 голосов
/ 06 июля 2011

Ничего.Среда выполнения не знает о Dispose методе, и вызов этого метода внутри оператора using ничего не делает для управления памятью.

Сборка мусора полностью связана с управлением памятью, но IDisposableFinalizer) - этоуправление ресурсами, так что вам все равно стоит подумать и реализовать это вручную (и правильно, например отписаться в Dispose).

...