除了多次使用它会违反DRY原则之外,你能看到这种单线的缺点吗?这似乎很简单,但我没有看到其他人提出它的事实让我想知道它是否有缺点。
这段代码创建了一个对方法的WeakReference,然后注册了一个调用引用目标的事件处理程序。
SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)();
谢谢,
本
除了多次使用它会违反DRY原则之外,你能看到这种单线的缺点吗?这似乎很简单,但我没有看到其他人提出它的事实让我想知道它是否有缺点。
这段代码创建了一个对方法的WeakReference,然后注册了一个调用引用目标的事件处理程序。
SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)();
谢谢,
本
我认为该模式不会达到您的预期。您是否试图阻止事件持有对当前对象的引用以防止内存泄漏?lambda 表达式将捕获 的值this
以进行评估ProcessEvent
(假设ProcessEvent
是实例方法),因此您仍然会有泄漏。这段代码和做的一样SomeEvent += (sender, e) => ProcessEvent();
。
您可能正在尝试做更多类似这样的事情(这也不是您想要的):
var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();
现在 lambda 表达式将捕获 WeakReference,因此您不会对this
. 不幸的是,没有其他东西引用从 ProcessEvent 创建的委托,因此即使它还this
活着,它也会在下一次 GC 时被删除。(这也不检查 Target 是否为空)。
你可以尝试这样的事情:
public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
var reference = new WeakReference(action.Target);
var method = action.Method;
EventHandler handler = null;
handler = delegate(object sender, EventArgs e)
{
var target = reference.Target;
if (target != null)
{
method.Invoke(target, null);
}
else
{
remove(handler);
}
};
return handler;
}
然后像这样使用它:
SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);
这将保持对 ProcessEvent 接收者的弱引用,并在事件收集后自动从事件中删除事件处理程序,只要定期引发事件,这应该可以防止内存泄漏。
它不是很可读。而且,如果您必须通过单步调试来调试它,那么这些操作中的任何一个都可能会失败,但那一行会失败。此外,您只会得到堆栈跟踪中引用的那一行。
为了可维护性,您通常希望避免在一行中做太多事情。