Ответ 1
Да, да. Издатели событий держат ссылки на объекты и не мешают им собирать мусор.
Посмотрите пример, чтобы узнать, что произойдет. У нас есть два класса; один раскрывает событие, другой потребляет его:
class ClassA
{
public event EventHandler Test;
~ClassA()
{
Console.WriteLine("A being collected");
}
}
class ClassB
{
public ClassB(ClassA instance)
{
instance.Test += new EventHandler(instance_Test);
}
~ClassB()
{
Console.WriteLine("B being collected");
}
void instance_Test(object sender, EventArgs e)
{
// this space is intentionally left blank
}
}
Обратите внимание, что ClassB не хранит ссылку на экземпляр ClassA; он просто подключает обработчик событий.
Теперь посмотрим, как собираются объекты. Сценарий 1:
ClassB temp = new ClassB(new ClassA());
Console.WriteLine("Collect 1");
GC.Collect();
Console.ReadKey();
temp = null;
Console.WriteLine("Collect 2");
GC.Collect();
Console.ReadKey();
Мы создаем экземпляр ClassB и сохраняем ссылку на него через временную переменную. Он получает новый экземпляр ClassA, где мы не храним ссылку на него в любом месте, поэтому он выходит за пределы области сразу после завершения конструктора ClassB. У нас есть сборщик мусора, который запускается один раз, когда ClassA вышел из сферы действия, и однажды, когда ClassB вышел из сферы действия. Выход:
Collect 1
A being collected
Collect 2
B being collected
Сценарий 2:
ClassA temp = new ClassA();
ClassB temp2 = new ClassB(temp);
temp2 = null;
Console.WriteLine("Collect 1");
GC.Collect();
Console.ReadKey();
temp = null;
Console.WriteLine("Collect 2");
GC.Collect();
Console.ReadKey();
Создается новый экземпляр класса ClassA, и ссылка на него сохраняется в переменной temp. Затем создается новый экземпляр ClassB, который получает экземпляр ClassA в temp, переданный ему, и мы храним ссылку на него в temp2. Затем мы устанавливаем temp2 равным null, делая экземпляр ClassB выходящим из области видимости. Как и раньше, мы запускаем сборщик мусора после того, как каждый экземпляр вышел из сферы действия. Выход:
Collect 1
Collect 2
B being collected
A being collected
Итак, в заключение; если экземпляр, который выдает событие, выходит за рамки, он становится доступным для сбора мусора, независимо от того, подключены ли обработчики событий или нет. Если экземпляр с обработчиком событий подключен к событию в другом экземпляре, он не будет доступен для сбора мусора до тех пор, пока обработчик события не будет удален или экземпляр, к которому прикреплен обработчик события, станет доступен для сбора мусора.