I have a base class DockedToolWindow : Form, and many classes that derive from DockedToolWindow. I have a container class that holds and assigns events to DockedToolWindow objects, however I want to invoke the events from the child class.
I actually have a question about how to implement what this MSDN site is telling me to do. This section below is giving me the problem:
// The event. Note that by using the generic EventHandler<T> event type
// we do not need to declare a separate delegate type.
public event EventHandler<ShapeEventArgs> ShapeChanged;
public abstract void Draw();
//The event-invoking method that derived classes can override.
protected virtual void OnShapeChanged(ShapeEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<ShapeEventArgs> handler = ShapeChanged;
if (handler != null)
{
handler(this, e);
}
}
Sure this example compiles and works, but when I replace "ShapeChanged" with "Move" (an event I acquired from deriving from Form), it errors saying I cannot have Move on the right side without += or -=. I also removed the ShapeEventArgs generic tags.
Any incite on why this isn't working? What's the difference between an event declared within the class and one that is inherited?
To do this, you can create a protected invoking method in the base class that wraps the event. By calling or overriding this invoking method, derived classes can invoke the event indirectly. Do not declare virtual events in a base class and override them in a derived class.
// As base-class pointer cannot access the derived class variable.
The derived class inherits all members and member functions of a base class. The derived class can have more functionality with respect to the Base class and can easily access the Base class. A Derived class is also called a child class or subclass.
The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive.
You cannot directly fire base class events. This is exactly the reason why you had to make your OnShapeChanged
method protected
instead of private
.
Use base.OnMove() instead.
From the C# language spec, section 10.7 (emphasis added):
Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. To be used in this way, an event must not be abstract or extern, and must not explicitly include event-accessor-declarations. Such an event can be used in any context that permits a field. The field contains a delegate (§15) which refers to the list of event handlers that have been added to the event. If no event handlers have been added, the field contains null.
Thus, the reason you can't treat the Move event like a field is that it is defined in a different type (in this case, your superclass). I agree with @womp's speculation that the designers made this choice to prevent unintended monkeying with the event. It seems obviously bad to allow unrelated types (types not derived from the type declaring the event) to do this, but even for derived types, it might not be desirable. They probably would have had to include syntax to allow the event declaration to be made private
or protected
with respect to field-style usage, so my guess is that they opted to just disallow it entirely.
The difference is scope. Inside your class, you can control how your event delegates are handled, however, your class cannot control what the base class is doing. It might be doing some crazy behind-the-scenes stuff with the event and its handlers. If you simply "reassigned" the Move event, you would be wiping out the multicast delegate list for the event.
I'm guessing they put a compiler restriction on this because its a very unsafe practice, and would essentially give any descendant class the ability to destroy the event model of its parent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With