I have a base class and a derived class .
The base class has a simple button with a virtual protected button click method.
I am using the ovverride keyword (not using new as i want the buttonclick method in the derived class to override the base class buttonclick method)
However , the code inside the derived class buttonclick method executes twice instead of once
Here is the code example
In the Base Class:
this.ok.Click += new System.EventHandler(this.ok_Click);
protected virtual void ok_Click(object sender, EventArgs e)
{
MessageBox.Show("From the Base class");
}
In the Derived Class:
this.ok.Click += new System.EventHandler(this.ok_Click);
protected override void ok_Click(object sender, EventArgs e)
{
MessageBox.Show("From the Derived class");
}
You haven't said what's actually calling the buttonclick method, but I suspect it's an event handler... and I suspect you're subscribing to it in both the subclass and base class constructors. Don't do that - you only need to subscribe once.
(If that's not the case, please show a short but complete example.)
Related
I am trying to understand for which purpose the events pattern decided that the method that fires the event should be declared virtual.
From C#6 in a Nutshell, from Joseph and Ben Albahari, O'Reilley:
Finally, the pattern requires that you write a protected virtual method that fires the
event. The name must match the name of the event, prefixed with the word On, and
then accept a single EventArgs argument:
Below a snippet I created to try to investigate.
I had the impression that the idea was to allow inheriting classes to completely overwrite how the event is handled, out of the box (original class). But the snippet below shows this is not possible, because deriving classes will never be able to invoke the event objects themselves (by the one one of the goals of the constraints imposed by the keyword event on delegates). The event can be invoked only in the containing class.
Now, since the pattern also asks that the method that fires the event simply check if the the event is not null and then call the delegate, with whatever every subscriber asked to do, what is left to be achieved by having the method that fires the event as virtual ? Inheriting classes are obliged to invoke the event the way it is in the broadcaster class, so all that is left for them is to add functionality. But this is exactly what they can achieve by subscribing to the event, in other words, by adding a call to an external function the time the event is fired.
I hope my wording is clear enough.
namespace eventsPatternVirtualEventFirerer
{
internal class Program
{
private static void Main(string[] args)
{
var obj = new X();
obj.ev += Obj_ev;
obj.Start();
}
private static void Obj_ev(object sender, EventArgs e)
{
Console.WriteLine("subscriber code...");
}
}
public class X
{
public event EventHandler<EventArgs> ev;
protected virtual void OnEvent(EventArgs e)
{
Console.WriteLine("original implementation...");
ev?.Invoke(this, e);
}
public void Start()
{
OnEvent(EventArgs.Empty);
}
}
public class X2 : X
{
public X2()
{
}
protected override void OnEvent(EventArgs e)
{
Console.WriteLine("inheriting class implementation overwrite...");
//compilation error - "the event 'X.ev' can only appear on the left hand side of += or -= (except when used from within the type 'X')"
ev?.Invoke(this, e);
}
}
}
I think the purpose is to allow derived classes to do something before/after the event is fired
public class X2 : X
{
public X2()
{
}
protected override void OnEvent(EventArgs e)
{
// Do something before the event
base.OnEvent(e);
// Do something after the event
}
}
There are a few things you can add/change in a derived class
Add a OnBeforeEvent / OnAfterEvent addition.
Choose not to broadcast the event (by conditionally not calling base.OnEvent(e)).
Vary the event args in some way.
Additionally, If you think about the way something like a page model works, it typically fires a Load event to notify when the page is loaded. Without a protected OnLoad method, derived classes would have to subscribe to it's own Load event to perform some action on load
public class MyPage : Page
{
protected override void OnLoad(EventArgs e)
{
// do something when the page is loaded
base.OnLoad(e);
}
}
versus:
public class MyPage : Page
{
public MyPage() : base()
{
this.Load += (sender,e) => {
// bleugh - subscribing to my own events
}
}
}
A good example might be the Paint event in Windows Forms.
// in MyButton : BaseButton : Control
void override OnPaint(object s, PaintEveargs e)
{
base.OnPaint(s, e); // Control: Draw background, BaseButton: draw border
// draw my own stuff
}
A button has several layers of base class, each drawing on top of each other.
I have an issue with overriding a method. I have created a base class with custom code that I want to run during the OnLoad event. The code in this overridden method applies to 90% of the pages that inherit from it, but on a few pages I need to override the override. My issue is that I still need to run the System.Web.UI.Page's OnLoad implementation. If I include the base.OnLoad(e) line in the second class (see below), it calls the BasePageEdit's logic, but if I remove it, the Page_Load event is never called. How can I skip over the logic in BaseEditPage's, and still get the functionality from System.Web.UI.Page?
public class BasePageEdit : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
// I need this to raise the Page_Load Event!
base.OnLoad(e); // Calls System.Web.UI.Page OnLoad Event which I want.
// Logic that I want to run in ADDITION to base Implementation;
}
// Other classes and methods;
}
public class WebPageThatNeedsSpecialOnLoadImplementation : BasePageEdit
{
protected override void OnLoad(EventArgs e)
{
// I need this to raise the Page_Load Event!
base.OnLoad(e); // If I include this, it runs the BasePageEdit, I don't want that...
// But I still need to run the System.Web.UI.Page onLoad event or Page_Load will not be called.
// Logic that I want to run INSTEAD of the logic from the override from BasePageEdit.
}
}
Thank you very much Slaks! I am editing my question to show how I implemented so that others viewing this post can implement the same way if they choose!
public class BasePageEdit : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
BasePage_OnLoad(e);
// Logic that I want to run in ADDITION to base Implementation;
}
protected virtual void BasePage_OnLoad(EventArgs e)
{
base.OnLoad(e);
}
// Other classes and methods;
}
public class WebPageThatNeedsSpecialOnLoadImplementation : BasePageEdit
{
protected override void OnLoad(EventArgs e)
{
BasePage_OnLoad(e);
// Logic that I want to run INSTEAD of the logic from the override from BasePageEdit.
}
}
You can't do that.
However, you can make a new method in BasePageEdit which just calls its base.OnLoad, and call that directly from the derived class instead.
I have something like this
class Super{
public event EventHandler MyEvent;
public void Enable(){
MyEvent+=AtEvent;
}
public void Disable(){
MyEvent-=AtEvent;
}
protected void AtEvent(object sender,EventArgs e){
AllThatJazz();
}
}
class Child:Super{
protected new void AtEvent(object sender,EventArgs e){
try{
base.AtEvent(sender,e);
}catch(ObjectDisposedException){}
}
}
class Program{
public static void Main(){
Child c = new Child();
c.Enable();
}
}
c.Enable() attaches the base class's event handler to MyEvent, not the Child's new AtEvent method. Can somebody explain this?
I appreciate suggestions for alternatives, but note that Super is in a separate assembly.
AtEvent is not virtual, it's sealed. You're calling it from a method in the base class, so it is going to be statically bound to that specific implementation of the method. It would need to be virtual (and overridden instead of shadowed) to call the most-derived implementation of that method, or it would need to be called from a reference to the object that was statically typed to Child, which is not currently the case at the place in which you call AtEvent.
Ive implemented an event in a object like this:
public class BaseObject
{
public delegate void NavigateHandler(object sender, EventArgs e);
public virtual event NavigateHandler Navigate;
A child og that base tries to invoke it:
public class ChildObject : BaseObject
{
private void DoNavigate()
{
Navigate(null, null);
This part above is broken, VS2012 tells me that I cant use Navigate in that manner.
However, it works fine to "hook" on that event if I instansiate a object of ChildObject:
ChildObject obj = new ChildObject();
obj.Navigate += foo_Navigate;
Where did I go wrong? I want to trigger that navigate event in the DoNavigate method.
You are only allow to invoke events from within the class that defines it.
If you want to allow sub-classes to fire the event then create a protected method (by convention it would be called OnNavigate) that fires the event and that can be accessed from implementing classes.
In my product I need process wide events. For that I used code like this:
public class Global
{
public static event EventHandler<MyEventArgs> Message;
public static void ShowMessage();
}
Now let's say I have a WinForms user interface. In form's code I will subscribe to this event and handle it in some default way (eg. by using System.Windows.Forms.MessageBox.Show() method). Now the question is how do I allow user to create derived form and override my default Message event handler implementation?
Just subscribing to the event for the second time with custom implementation doesn't solve the problem (both event handlers would be executed and potentially two message boxes shown). The options I see are either:
//call OnSubscribeToMessageEvent() from either form's constructor or OnLoad event handler
protected virtual void OnSubscribeToMessageEvent()
{
Global.Message += new EventHandler<MyEventArgs>(Global_Message);
}
private void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
or
//subscribe in either form's constructor or OnLoad event handler
protected virtual void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
Which version is better and why? Or maybe there are any other options?
I still have some doubts as I have never seen such a design pattern in any .NET library
Yes, you're right to worry about this. These kind of event subscriptions are very fickle, the event source always outlives the subscriber. There's only one class in the framework I know that does this, SystemEvents. The problem is that every subscriber has to very carefully unsubscribe itself when its lifetime ends or the object will stay referenced forever. A memory leak that's very hard to diagnose.
A better pattern here is to use an interface. Let's declare one:
public class MyEventArgs { /* etc.. */ }
public interface IGlobalNotification {
event EventHandler Disposed;
void OnMessage(MyEventArgs arg);
}
Now you can have a form implement the interface:
public partial class Form1 : Form, IGlobalNotification {
public Form1() {
InitializeComponent();
GlobalMessages.Register(this);
}
void IGlobalNotification.OnMessage(MyEventArgs arg) {
// do something
}
}
The Register method registers the form with the GlobalMessages class, the Dispose event ensures that the class can detect that the form is dying:
public static class GlobalMessages {
public static void Register(IGlobalNotification listener) {
listener.Disposed += delegate { listeners.Remove(listener); };
listeners.Add(listener);
}
public static void Notify(MyEventArgs arg) {
foreach (var listener in listeners) listener.OnMessage(arg);
}
private static List<IGlobalNotification> listeners = new List<IGlobalNotification>();
}
Call GlobalMessages.Notify() to get the OnMessage() method to run in all live form instances. The major advantage of this approach is that a client programmer can never screw up.
I would let the derived class override the Global_Message. The subscription to the event is generic and why would you want to implement it in every child again? It also gives you the option to call base.Global_Message(sender, e) in case your child class just wants to add some decoration to it and use the default behaviour otherwise.
I would prefer your second example, as that way, classes that extend your base class only have to override one method and do not have to remove the handler added by the base class from the event.
The key is adding the virtual keyword, so that a derived type can overide the method and the method they created will be called instead.
//subscribe in either form's constructor or OnLoad event handler
protected virtual void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
Now that you've added virtual to both, I'd go with the first and override the one that subscribes to the event, if they didn't want the event subscribed to.
Though there is another option, call it #3.
protected EventHandler GlobalMessageEvent = new EventHandler<MyEventArgs>(Global_Message);
protected virtual void OnSubscribeToMessageEvent()
{
// this could be done in the Form_Load() or constructor instead.
Global.Message += GlobalMessageEvent;
}
Then potentially an inherited class could do somewhere: (note the -=)
{
Global.Message -= GlobalMessageEvent;
}