Event handlers, existing class to new interface
I'm building in some flexibility to a program, given its purpose has now changed. I want to add in an interface which an existing class will implement.
Existing Class
public class ClassA
{
#region Events
public delegate void DataReceivedHandler(object sender, EventArgs e);
public delegate void DataSentHandler(object sender, EventArgs e);
public delegate void StatusUpdatedHandler(object sender, EventArgs e);
public event DataReceivedHandler DataReceived;
public event DataSentHandler DataSent;
public event StatusUpdatedHandler StatusUpdated;
#endregion
//rest of code here...
}
New Interface
public interface IClassA
{
event EventHandler DataReceived;
event EventHandler DataSent;
event EventHandler StatusUpdated;
//rest of code here...
}
My three questions开发者_开发技巧 are as follows.
Q1. Am I right in the first place to declare my own delegates in the class i.e. public delegate void DataReceivedHandler
, or should these be removed and the events replaced with a normal EventHandler. i.e. public event EventHandler DataReceived
. Given that these events aren't passing data with the event, just notifying anything that has subscribed that something has changed.
Q2. Tied closely to the question above. Given I am changing the properties of the class, i.e. status (StatusUpdated). Is it best practice to pass the new state as a custom EventArgs, thus requiring a custom delegate as in the original code? As it currently works the event is fired, and the subscribed class can just use the sender value, i.e. (sender as ClassA).Status. Is there a best practice or is it just up to the developer?
Q3. Now that is out the way. The part about the interface. Have I correctly declared the DataReceived and other events in the interface, to match the class that will be marked as implementing it.
If you need custom delegates for interface methods, you should declare them separately (outside a class), because they are not tied to a specific implementation. A delegate declaration can sit inside an interface, just like a class does. The issue with your delegates is that they all have the same signature (that of an EventHandler
), and are therefore redundant.
If you don't need to pass any data when raising those events, you can use a plain EventHandler delegate. However, I would expect to get some data with a DataReceived
event, so you should check if that makes sense and possibly use a delegate which accepts some data as a parameter.
Third, your interface event signatures must match class signatures. You cannot use an EventHandler
delegate type in an interface, and change the signature inside the class.
Note that you can also avoid declaring delegate types explicitly, and used generic Action
delegates provided with the BCL (starting with in .NET 3.5). In that case you might have something like:
public interface IClassA
{
event Action<IClassA, Data> DataReceived;
event Action<IClassA, Data> DataSent;
event Action<IClassA, Status> StatusUpdated;
}
The latter approach gives you the benefit of having a strongly typed sender
parameter (opposed to an object
in EventHandler
).
In answer to your questions, of course these are a matter of opinion so i'll give mine:
A1) No, you are not right to re-declare your own XXXHandler
delegates, there is one in the framework (EventHandler
) exactly matching yours - a good indication you're "re-inventing the wheel".
A2) I believe that an event called StatusChanged
should pass the new (and potentially the old) status to any subscribers. However this is still not a reason to implement your own delegate, as the framework defines a generic delegate (EventHandler<TEventArgs>
) for exactly this purpose.
A3) At the moment you're class' events do not match the interface, meaning that it will not be able to implemnt it without change.
Docs: EventHandler<TEventArgs>
精彩评论