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
不是参数时起作用,所以不清楚它从何而来。如果它是一个实例变量,我相信最终会有一个委托指向一个实例方法,并且具有相同目标对象的任何两个这样的委托都是相等的。