In following code, I want to extend the behaviour of a class by deriving/subclassing it, and make use of an event of the base class:
public class A { public event EventHandler SomeEvent; public void someMethod() { if(SomeEvent != null) SomeEvent(this, someArgs); } } public class B : A { public void someOtherMethod() { if(SomeEvent != null) SomeEvent(this, someArgs); // << why is this not possible? //Error: The event 'SomeEvent' can only appear on the left hand side of += or -= //(except when used from within the type 'A') } }
Why isn't it possible?
And what is the common solution for this kind of situation?
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.
Inheritance enables you to create new classes that reuse, extend, and modify the behavior defined in other classes. 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.
Inheritance was invented in 1969 for Simula and is now used throughout many object-oriented programming languages such as Java, C++, PHP and Python. An inherited class is called a subclass of its parent class or super class.
Usually you use a derived class when an existing class provides members that the new class can use, or when you want to extend or embellish existing class properties and methods. This is called inheritance: the new class inherits, and has direct access to, all Public and Private members of the existing base class.
Others have explained how to get round the issue, but not why it's coming up.
When you declare a public field-like event, the compiler creates a public event, and a private field. Within the same class (or nested classes) you can get at the field directly, e.g. to invoke all the handlers. From other classes, you only see the event, which only allows subscription and unsubscription.
The standard practice here is to have a protected virtual method OnSomeEvent on your base class, then call that method in derived classes. Also, for threading reasons you will want to keep a reference to the handler before checking null and calling it.
For an explanation of the why read Jon Skeet's answer or the C# specification which describes how the compiler automatically creates a private field.
Here is one possible work around.
public class A { public event EventHandler SomeEvent; public void someMethod() { OnSomeEvent(); } protected void OnSomeEvent() { EventHandler handler = SomeEvent; if(handler != null) handler(this, someArgs); } } public class B : A { public void someOtherMethod() { OnSomeEvent(); } }
Edit: Updated code based upon Framework Design Guidelines section 5.4 and reminders by others.
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