C# 取消订阅匿名委托的事件
我想知道如何取消订阅活动中的匿名方法 我已经检查过了,但我的情况有点不同 我使用匿名方法访问局部函数变量 代码如下C# 取消订阅匿名委托的事件,c#,.net,events,delegates,closures,C#,.net,Events,Delegates,Closures,我想知道如何取消订阅活动中的匿名方法 我已经检查过了,但我的情况有点不同 我使用匿名方法访问局部函数变量 代码如下 private static void Test(Object dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { if (dependencyPropertyChangedEventArgs.OldValue is Obser
private static void Test(Object dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
if (dependencyPropertyChangedEventArgs.OldValue is ObservableCollection<object>)
{
(dependencyPropertyChangedEventArgs.OldValue as ObservableCollection<object>).CollectionChanged -=
(s, e) => SelectedItemsChanged(dependencyObject, e); // TO FIX event unbsubscription via anonymous delegate
}
if (dependencyPropertyChangedEventArgs.NewValue is ObservableCollection<object>)
{
(dependencyPropertyChangedEventArgs.NewValue as ObservableCollection<object>).CollectionChanged +=
(s, e) => SelectedItemsChanged(dependencyObject, e);
}
}
私有静态无效测试(对象dependencyObject,DependencyPropertyChangedEventArgs DependencyPropertyChangedEventArgs)
{
如果(dependencyPropertyChangedEventArgs.OldValue为ObservableCollection)
{
(dependencyPropertyChangedEventArgs.OldValue作为ObservableCollection)。CollectionChanged-=
(s,e)=>SelectedItemsChanged(dependencyObject,e);//通过匿名委托修复事件订阅
}
if(dependencyPropertyChangedEventArgs.NewValue为ObservableCollection)
{
(dependencyPropertyChangedEventArgs.NewValue作为ObservableCollection)。CollectionChanged+=
(s,e)=>SelectedItemsChanged(dependencyObject,e);
}
}
对于匿名代理,您不能这样做。
为了能够取消订阅,您必须使用常用的代理。新答案,现在问题已更改 基本上,你不能。处理程序依赖于
dependencyObject
,每次调用时都会在一个新对象中捕获该对象,因此最终会得到不相等的委托
您可以创建一个新类,该类保存依赖项对象并覆盖Equals
,以比较这些对象,而不是使用匿名函数,或者您可以只保存对以前订阅的处理程序的引用
学员不依赖参数时的旧答案 奇怪的是,在这种特殊情况下,似乎没有捕获任何局部变量。因此,如果您订阅事件的唯一地点是此方法,则您可能会逃脱:
private static void Test(Object a, DependencyPropertyChangedEventArgs args)
{
NotifyCollectionChangedEventHandler handler =
(s, e) => SelectedItemsChanged(dependencyObject, e);
var oldObservable = args.OldValue as ObservableCollection<object>;
if (oldObservable != null)
{
oldObservable.CollectionChanged -= handler;
}
var newObservable = args.NewValue as ObservableCollection<object>;
if (newObservable != null)
{
newObservable.CollectionChanged += handler;
}
}
私有静态无效测试(对象a,DependencyPropertyChangedEventArgs参数)
{
NotifyCollectionChangedEventHandler处理程序=
(s,e)=>SelectedItemsChanged(dependencyObject,e);
var oldObservable=args.OldValue作为ObservableCollection;
如果(oldObservable!=null)
{
oldObservable.CollectionChanged-=处理程序;
}
var newObservable=args.NewValue作为ObservableCollection;
if(newObservable!=null)
{
newObservable.CollectionChanged+=处理程序;
}
}
由于您现在只有一个lambda表达式,我希望将其转换为单个静态方法,因此新创建的委托将与原始委托相同
然而,我不建议这样做。我只需要自己创建方法,然后使用方法组转换。您的案例在哪些方面有所不同?你根本做不到这一点——这是行不通的。不同之处在于我需要提供变量local对函数的访问。如果我选择使用命名方法,如何传递这个变量。我的问题中有输入错误。第一个参数应该是dependencyObject(不是一个)。如何使用方法组转换(并将dependencyObject传递给方法)?@Tilak:在这种情况下,您不能,您应该存储处理程序。我会编辑。@Tilak:以后,如果更改对意思有重大影响,请不要编辑我的答案。结果是无法工作的代码,也与我的描述不符。@JonSkeet您确定这将删除在上一次迭代中添加的相同处理程序吗?我期待着不可预测的结果。或者这是因为没有捕获的变量才起作用吗?@StephaneDelcroix:我相信这是可以的,因为它没有捕获任何东西-但这只在
dependencyObject
不是参数时起作用,所以不清楚它从何而来。如果它是一个实例变量,我相信最终会有一个委托指向一个实例方法,并且具有相同目标对象的任何两个这样的委托都是相等的。