2

I want to know how to unsubscribe anonymous methods from the events.

I have already checked Unsubscribe anonymous method in C# but my case is little different.

I am accessing local function variable in the anonymous method.

Code is as below

 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);
        }
    }
Community
  • 1
  • 1
Tilak
  • 30,108
  • 19
  • 83
  • 131
  • 1
    In what way is your case different? You simply can't do this - it won't work. See http://stackoverflow.com/questions/1348150/how-do-i-unregister-anonymous-event-handler too. – Jon Skeet Jun 22 '12 at 08:28
  • difference is that i need to provide access of variable local to function. How to pass this variable, if i choose to use named method. – Tilak Jun 22 '12 at 09:25

2 Answers2

2

You can not do that with anonymous delegates. In order to be able to unsubscribe you have to use usual delegates.

Tigran
  • 61,654
  • 8
  • 86
  • 123
1

New answer, now the question has changed

You can't, basically. Your handler depends on dependencyObject, which will be captured in a new object on each call, so you'll end up with unequal delegates.

You could create a new class which holds the dependency object and overrides Equals to compare those objects instead of using anonymous functions, or you could just hold a reference to the previously-subscribed handler.


Old answer, when the delegate didn't depend on the parameters

The bizarre thing is that in this particular case, it looks like you're not capturing any local variables. So it's possible that if the only place you're subscribing to the event is from this method, you could get away with:

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

As you've only got one lambda expression now, I'd expect that to be converted into a single static method, so the freshly-created delegate will be equal to the original one.

However, I wouldn't recommend that. I'd just create the method yourself, and then use a method group conversion.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • There was typo in my question. First parameter should be dependencyObject (not a). How to use method group conversion (and pass dependencyObject to the method)? – Tilak Jun 22 '12 at 09:40
  • @Tilak: In that case, you can't, and you should store the handler instead. I'll edit. – Jon Skeet Jun 22 '12 at 11:03
  • @Tilak: In future, please don't edit my answers when the change makes a significant difference to the meaning. The result was code that *wouldn't* have worked, and which didn't gel with my description either. – Jon Skeet Jun 22 '12 at 11:06
  • @JonSkeet are you sure this will remove the same handler that was added in a previous iteration? I'm expecting unpredictable results here. Or does this works because there's no captured variable ? – Stephane Delcroix Nov 21 '13 at 14:18
  • @StephaneDelcroix: I *believe* it would be okay because it's not capturing anything - but that only worked when `dependencyObject` wasn't a parameter, so it wasn't clear where that was coming from anyway. If it were an instance variable, I believe it would end up with a delegate targeting an instance method, and any two such delegates with the same target object would be equal. – Jon Skeet Nov 21 '13 at 14:23