如果我执行以下操作:
public class Test
{
public static void Main()
{
List<Person> persons = new List<Person> { new Person() };
persons[0].Sneezing += new EventHandler(Person_Sneezing);
persons = null;
}
public static void Person_Sneezing(object sender, EventArgs e)
{
(sender as Person).CoverFace();
}
}
亲自[0]的人是否仍然存在于内存中,因为它的打喷嚏代表有对Person_Sneezing方法的引用或是否由GC收集?
答案 0 :(得分:8)
这将由GC收集。要保留在内存中,对象必须由...直接或间接引用。
对于人物[0]的物体不是这样。所以它将被收集。
当然,假设Person()的构造函数没有做任何有趣的事情,比如将自己添加到ThreadLocalStorage。
答案 1 :(得分:6)
你已经到了一半;如果它是其他方式,这将是一个内存泄漏。也就是说,如果它看起来像这样:
public class Test
{
public void HookupStuff()
{
List<Person> persons = new List<Person> { new Person() };
this.EventHappened += new EventHandler(persons[0].SomeMethod);
// persons[0].Sneezing += new EventHandler(Person_Sneezing);
persons = null;
}
}
现在persons[0]
会坚持下去,即使你排除了persons
,因为父类有一个方法可以引用它。
答案 2 :(得分:1)
除了你已经得到的答案之外,你需要在更现实的例子中小心。
如果您的应用程序有一个主窗口,只要程序运行就会存活,并且您经常创建“短期”对象,将其方法登记到主窗口上的事件,那么您必须从这些事件中删除对象。你不再需要它们,因为否则这些对象根本就不会“短暂” - 它们只要在主窗口中存活,即直到用户关闭应用程序。有效的结果将等同于内存泄漏。
如果您创建短期对象的类实现IDisposable
,它可以帮助您,因此您可以从Dispose
中的事件中退出,然后确保在要放弃对象时调用dispose