为了解释我对 John Fenton 帖子的评论,这是我的回答。让我们看看下面的例子:
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
a.Clicked += b.HandleClicked;
//a.Clicked += B.StaticHandleClicked;
//A.StaticClicked += b.HandleClicked;
var weakA = new WeakReference(a);
var weakB = new WeakReference(b);
a = null;
//b = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("a is alive: " + weakA.IsAlive);
Console.WriteLine("b is alive: " + weakB.IsAlive);
Console.ReadKey();
}
}
class A
{
public event EventHandler Clicked;
public static event EventHandler StaticClicked;
}
class B
{
public void HandleClicked(object sender, EventArgs e)
{
}
public static void StaticHandleClicked(object sender, EventArgs e)
{
}
}
如果你有
a.Clicked += b.HandleClicked;
并且仅将 b 设置为 null 两个引用 weakA 和 weakB 都保持活动状态!如果您仅将 a 设置为 null b 保持活动状态但 a 不存在(这证明 John Fenton 错误地指出硬引用存储在事件提供程序中 - 在本例中为 a)。
这导致我得出一个错误的结论,即
a.Clicked += B.StaticHandleClicked;
会导致泄漏,因为我虽然 a 的实例将由静态处理程序保留。事实并非如此(测试我的程序)。在静态事件处理程序或事件的情况下,情况正好相反。如果你写
A.StaticClicked += b.HandleClicked;
将保留对 b 的引用。