2015-08-13 13 views
10

Diciamo che ho un ObservableCollection di classi:Cancellati da eventi in ObservableCollection

CustomClassName testClass = new CustomClassName(); 
ObservableCollection<CustomClassName> collection = new ObservableCollection<CustomClassName>(); 
testClass.SomeEvent += OnSomeEvent; 
collection.add(testClass); 

Quando sarò rimuovere elementi da una collezione, ho bisogno manualmente annullare l'iscrizione a eventi (OnSomeEvent) o dovrei lasciare per un GC? E qual è il modo migliore per annullare l'iscrizione?

risposta

5

Se si prevede di ritirare l'articolo, è necessario annullare l'iscrizione.

Per fare ciò, il modo usuale è:

collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(collection_CollectionChanged); 

// ... 
// and add the method 
void collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) 
    { 
     foreach (var it in e.OldItems) { 
      var custclass = it as CustomClassName; 
      if (custclass != null) custclass.SomeEvent -= OnSomeEvent; 
     } 
    } 
} 
+0

Thnx. E qual è il modo migliore? Lo sto facendo in collectionChanged. – Sasha

0

Non è necessario per annullare l'iscrizione in caso normale.

L'evento abbonato non può impedire l'editore (testClass) di essere raccolti, ma il contrario può accadere. Non riesco a vedere nulla mantenendo lo testClass attivo, eccetto lo ObservableCollection.

testClass.SomeEvent += this.OnSomeEvent; 

testClass è mantenere vivo perché thisthis viene memorizzato nella lista invocazione testClass.SomeEvent s'(in modo tale che OnSomeEvent viene chiamato quando c'è un SomeEvent). this non manterrà vivo testClass sottoscrivendo l'evento testClass.

Nel codice seguente, il obj viene rimosso dalla raccolta, ed è garbage collection senza cancellarsi, si può tentare di eseguire il codice per vedere il risultato:

void Main() 
{ 
    var obj = new BackgroundWorker(); 
    obj.DoWork += OnSomeEvent; 
    var oc = new ObservableCollection<object>{ obj }; 

    WeakReference objRef = new WeakReference(obj); 
    Console.WriteLine(objRef.IsAlive); 

    oc.Remove(obj); 
    obj = null; 
    GC.Collect(); 

    Console.WriteLine(objRef.IsAlive); 
} 

private void OnSomeEvent(object sender, DoWorkEventArgs e) 
{ 
    Console.WriteLine("work"); 
} 

uscita:

vero
Falso

Si può dare un'occhiata in un similar question.

+0

cosa intendi per caso normale? – Sasha

+0

Poiché l'operatore + = può essere "sovraccaricato", quindi può succedere di tutto. Se si tratta solo di iscriversi a un evento, dovrebbe andare bene. –

+0

@Sasha Ho aggiunto del codice, puoi provare se è il tuo caso. –

Problemi correlati