我使用Resharper 5.1代码分析很多次我从resharper收到评论
“通过匿名代表取消订阅”
#Part of Code
if (((bool)e.NewValue))
{
listView.PreviewTextInput += (o,args) =>
listView_PreviewTextInput(o,args,listView);
}
else
{
listView.PreviewTextInput -= (o, args) =>
listView_PreviewTextInput(o, args, listView);
}
我怎样才能纠正或优化这件事
答案 0 :(得分:30)
您可以将lambda提取到变量:
EventHandler func = (sender, e) =>
listView_PreviewTextInput(sender, e, listView);
if (((bool)e.NewValue))
{
listView.PreviewTextInput += func;
}
else
{
listView.PreviewTextInput -= func;
}
答案 1 :(得分:12)
警告! 来自史蒂文的Accepted answer 错误,所有这一切只是掩盖了resharper警告的问题。
每次执行代码
EventHandler func = (sender, e) =>
listView_PreviewTextInput(sender, e, listView);
你会得到一个新的(因为你可以捕获不同的listView
)匿名委托的实例保存到func
,这个实例还没有订阅任何事件,所以反过来这个代码
listView.PreviewTextInput -= func;
将无效,因为您无法取消订阅您未订阅的活动。这将导致令人难以置信的错误,例如事件处理程序“被称为两次”,内存泄漏等。
实际上,Jon Skeet说may work in some cases:
C#规范明确规定(IIRC)如果你有两个 它可以是匿名函数(匿名方法或lambda表达式) 或者可能不会从该代码创建平等的代理。
e.g。当编译器每次都没有生成新实例时,你会看到很好的行为。
但这不可靠,当然在使用捕获的变量listView
的起始问题中描述的情况下也不会起作用。
所以我的建议是:
仅在您永远不必取消订阅时才使用匿名函数作为事件处理程序。