我试图了解事件如何导致内存泄漏。我在这个stackoverflow 问题上找到了一个很好的解释, 但是在查看 Windg 中的对象时,我对结果感到困惑。首先,我有一个简单的类,如下所示。
class Person
{
public string LastName { get; set; }
public string FirstName { get; set; }
public event EventHandler UponWakingUp;
public Person() { }
public void Wakeup()
{
Console.WriteLine("Waking up");
if (UponWakingUp != null)
UponWakingUp(null, EventArgs.Empty);
}
}
现在我在 Windows 窗体应用程序中使用这个类,如下所示。
public partial class Form1 : Form
{
Person John = new Person() { LastName = "Doe", FirstName = "John" };
public Form1()
{
InitializeComponent();
John.UponWakingUp += new EventHandler(John_UponWakingUp);
}
void John_UponWakingUp(object sender, EventArgs e)
{
Console.WriteLine("John is waking up");
}
private void button1_Click(object sender, EventArgs e)
{
John = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
MessageBox.Show("done");
}
}
如您所见,我实例化了 Person 类并订阅了 OnWakingUp 事件。我在这个表格上有一个按钮。当用户单击此按钮时,我将此 Person 实例设置为 null 而不取消订阅该事件。然后我调用 GC.Collect 以确保执行 Garbade 收集。我在这里显示一个消息框,以便我可以附加 Windbg 以查看 Form1 类的参考帮助,在此类中我没有看到对该事件的任何引用(Windbg 输出如下所示,尽管 Form1 的数据太长,我正在显示与我的问题有关)。此类具有对 Person 类的引用,但它为空。基本上这对我来说似乎不是内存泄漏,因为 Form1 没有任何对 Person 类的引用,即使它没有取消订阅该事件。
我的问题是这是否会导致内存泄漏。如果不是,为什么不呢?
0:005> !do 0158d334
Name: WindowsFormsApplication1.Form1
MethodTable: 00366390
EEClass: 00361718
Size: 332(0x14c) bytes
File: c:\Sandbox\\WindowsFormsApplication1\WindowsFormsApplication1\bin\Debug\WindowsFormsApplication1.exe
Fields:
MT Field Offset Type VT Attr Value Name
619af744 40001e0 4 System.Object 0 instance 00000000 __identity
60fc6c58 40002c3 8 ...ponentModel.ISite 0 instance 00000000 site
619af744 4001534 b80 System.Object 0 static 0158dad0 EVENT_MAXIMIZEDBOUNDSCHANGED
**00366b70 4000001 13c ...plication1.Person 0 instance 00000000 John**
60fc6c10 4000002 140 ...tModel.IContainer 0 instance 00000000 components
6039aadc 4000003 144 ...dows.Forms.Button 0 instance 015ad06c button1
0:008> !DumpHeap -mt 00366b70
Address MT Size
total 0 objects
Statistics:
MT Count TotalSize Class Name
Total 0 objects