C# 通过匿名委托取消订阅事件
我正在使用Resharper 5.1代码分析,很多时候我都会收到Resharper的评论 “通过匿名代表取消订阅事件”C# 通过匿名委托取消订阅事件,c#,wpf,attachedbehaviors,C#,Wpf,Attachedbehaviors,我正在使用Resharper 5.1代码分析,很多时候我都会收到Resharper的评论 “通过匿名代表取消订阅事件” #Part of Code if (((bool)e.NewValue)) { listView.PreviewTextInput += (o,args) => listView_PreviewTextInput(o,args,listView); } else { listView.PreviewTextInput -= (o, a
#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);
}
我如何纠正或优化这个问题您可以将lamdba提取到一个变量:
EventHandler func = (sender, e) =>
listView_PreviewTextInput(sender, e, listView);
if (((bool)e.NewValue))
{
listView.PreviewTextInput += func;
}
else
{
listView.PreviewTextInput -= func;
}
警告!
从《史蒂文是错的》中,它所做的只是掩盖了resharper警告的一个问题
每次执行给定代码时
EventHandler func = (sender, e) =>
listView_PreviewTextInput(sender, e, listView);
您将获得保存到func
的匿名委托的新实例(因为您可以捕获不同的listView
),该实例尚未订阅任何事件,因此依次执行此代码
listView.PreviewTextInput -= func;
实际上什么也做不了,因为你不能取消订阅你没有订阅的活动。这将导致令人难以置信的错误,如事件处理程序“调用两次”、内存泄漏等
事实上,Jon Skeet说:
C#规范明确规定(IIRC),如果您有两个
匿名函数(匿名方法或lambda表达式)它可能
或者不能从该代码创建相等的委托
e、 当编译器不每次生成新实例时,您将看到良好的行为
但这是不可靠的,在初学者问题中描述的带有捕获变量listView
的情况下肯定不起作用
因此,我的建议是:
仅当您永远不必取消订阅时,才将匿名函数用作事件处理程序。谢谢,但
事件处理程序应该是特定的,对吗??因为它给了我一个错误System.EvenTArgs不能分配给TextCompositionEventArgs
,在这种情况下listView。PreviewTimeput
不是EventHandler
,但可能是EventHandler
,但我无法知道,因为您在问题中没有说明这一点。是的。。我的错。。谢谢你……:)