2012-05-22 9 views
5

Gibt es einen Unterschied zwischen diesen beiden Implementierungen?Unterschied zwischen zwei Dispo-Implementierungen?

1:

public class SMSManager : ManagerBase 
{ 
    private EventHandler<SheetButtonClickEventArgs> _buttonClickevent; 

    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) : 
     base(smsDataBlock) 
    { 
     _buttonClickevent = new EventHandler<SheetButtonClickEventArgs>(OnButtonClick); 
     SheetEvents.ButtonClick += _buttonClickevent; 

    } 

    public override void Dispose() 
    { 
     base.Dispose(); 
     if (_buttonClickevent != null) 
     SheetEvents.ButtonClick -= _buttonClickevent; 
    } 
} 

2:

public class SMSManager : ManagerBase 
{ 
    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) : 
     base(smsDataBlock) 
    { 
     SheetEvents.ButtonClick += new EventHandler<SheetButtonClickEventArgs>(OnButtonClick); 
    } 

    public override void Dispose() 
    { 
     base.Dispose(); 
     SheetEvents.ButtonClick -= new EventHandler<SheetButtonClickEventArgs>(OnButtonClick); 
    } 
} 

Die erste scheint Speicherlecks in Bezug richtiger als die zweite ist. Aber ist das wirklich richtig?

+0

Vergessen Sie nicht, eine Antwort als die Antwort zu markieren, es hilft, den Inhalt auf dieser Site zu bereichern. –

Antwort

5

Das lange und kurze davon ist das zweite Stück Code ist korrekt und sicher (auch wenn keine Handler registriert sind).

Betrachten Sie diese Beispielanwendung:

namespace ConsoleApplication61 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var f = new Foo(); 
      f.MyEvent += new EventHandler(Handler); 
      f.Trigger(); 
      f.MyEvent -= new EventHandler(Handler); 
      f.Trigger(); 
      Console.Read(); 
     } 

     static void Handler(object sender, EventArgs e) 
     { 
      Console.WriteLine("handled"); 
     } 
    } 

    class Foo 
    { 
     public event EventHandler MyEvent; 
     public void Trigger() 
     { 
      if (MyEvent != null) 
       MyEvent(null, null); 
     } 
    } 
} 

Dieses Beispiel druckt einmal "behandelt".

Also in Ihrem Beispiel sind sie funktional gleich und beide funktionieren wie benötigt. Das Entfernen eines Handlers, der nicht hinzugefügt wurde, ist ebenfalls eine sichere Aktion, er findet einfach nichts zu entfernen und tut nichts.

Wie in den Kommentaren versehen, Marc Antwort geht mehr ins Detail:

Unregister events with new instance of the delegate


Event-Handler mit Anonyme Methoden

Es ist erwähnenswert, dass Event-Handler in Form Von Lambda-Ausdrücken wird nicht garantiert, dass sie die Eindeutigkeit basierend auf Instanz- und Methodensignatur erzwingen. Wenn Sie eine anonyme Methode austragen müssen, müssen Sie entweder sie ein Verfahren zur Förderung oder einen Verweis auf die anonyme Methode zur späteren Verwendung behalten:

Func<object, EventArgs> meth = (s, e) => DoSomething(); 

myEvent += meth; 
myEvent -= meth; 

Jon Skeet geht ins Detail diese zu beantworten und wahrscheinlich eine bessere Arbeit davon als ich :-)

How to remove a lambda event handler


eine leichte Refactoring

Ich würde zu folgendem refactor:

public class SMSManager : ManagerBase 
{ 
    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) 
     : base(smsDataBlock) 
    { 
     SheetEvents.ButtonClick += OnButtonClick; 
    } 

    public override void Dispose() 
    { 
     SheetEvents.ButtonClick -= OnButtonClick; 
     base.Dispose(); 
    } 
} 
+0

Siehe Marcs [Antwort] (http://Stackoverflow.com/a/714126/95573) – SwDevMan81

+0

@ SwDevMan81 Bingo! Ich habe nach diesen Informationen gesucht, ta. –

+0

@ SwDevMan81: Heute habe ich gelernt. (Es ist auch Marc, nicht Mark.) – BoltClock