Вопрос

Lets say I create an abstract class that manages some network functionality for me.

I want to be able to be notified when something changes. For example: OnConnect or OnDisconnect.

Should I create events for those kinds of functions or implement them as abstract methods?

public event OnConnectDelegate OnConnected;

or:

protected abstract OnConnected(SomeClientObject connectedClient);

I prototyped both solutions and both work as expected. But how do I know in general if I should expose functionality as an event or as an abstract method? Are there any situations where I should clearly prefer one over the other? Events support multiple receivers but one also has to remove them when the receiver doesn't need to receive them anymore.

Это было полезно?

Решение

Of the now partially outdated but still useful article from MSDN: "When to Use Delegates Instead of Interfaces (C# Programming Guide)", a few of the rules-of-thumb stand out:

Use a delegate in the following circumstances:

(3) The caller has no need to access other properties, methods, or interfaces on the object implementing the method.

My explanation:

The callee (event receiver) can easily get hold of the caller (sender) because by best practice the caller will pass itself as the first argument (aptly named sender) to the callee.

However, trying to navigate in the reverse direction is non-trivial. A delegate could be anything—a static method, or a lambda, or basically anything other than the real object that ultimately processes the event. Thus, one cannot always determine what that real object is.

The latter point could be worked around by using visitor pattern. However, that adds a lot of code and that makes any discussion moot.


Use an interface in the following circumstances:

(1) There is a group of related methods that may be called.

I would add a bit more: "... and that these related methods are to be found on the same object."

This question has been asked many times. Just search for "C#", "delegate", "interface" will yield a lot of results. However, it takes time to examine the numerous pieces of advice from all of the sources to sift out the relevant ones given your situation.

Другие советы

I'd suggest doing both!

Those on* methods are the ideal place from which to raise those events. (Well, it must have some merit; that's the way most, if not all, of the .Net Windows Controls work).

internal class Button2 : System.Windows.Forms.Button
   {
      protected overrides void onClick( EventArgs e )
      {
         if ( ! this.AmIgnoringTheUser() )
         } 
            // Ask the base Button control to raise the Click event 
            base.onClick( e ); 
         }
      }
   }

If your class is declared as "sealed" (/ "notinheritable" / "final"), then the above is probably the only reason to have the on* methods. You consumers can only attach event delegates.

This protects your class, in that people can't muck about with its innards, but it reduces its useability if its, say, a visible Control. Visual Inheritance makes extensive use of these overridable on* methods for the simple reason that you cannot guarantee the order in which event delegates are invoked. You can guarantee the order that the on* methods are called in.

Лицензировано под: CC-BY-SA с атрибуция
scroll top