2

我想知道如何从事件中取消订阅匿名方法。

我已经在 C# 中检查了 Unsubscribe 匿名方法,但我的情况略有不同。

我正在匿名方法中访问局部函数变量。

代码如下

 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);
        }
    }
4

2 回答 2

2

不能用匿名代表来做到这一点。为了能够取消订阅,您必须使用通常的代表。

于 2012-06-22T08:27:44.877 回答
1

新答案,现在问题变了

你不能,基本上。您的处理程序依赖于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;
    }
}

由于您现在只有一个lambda 表达式,我希望将其转换为单个静态方法,因此新创建的委托将等于原始委托。

但是,我不建议这样做。我只是自己创建方法,然后使用方法组转换。

于 2012-06-22T08:32:53.383 回答