Search code examples
c#inheritanceoverridingvirtualmethod-hiding

Base Virtual Method not called or called twice


Here my code.

public class EventItem
{
    public int Id { get; set; } = -1;
    public int ClientId { get; set; }

    public EventItem(IDataRecord rdr)
    {
        FillAttributs(rdr);
    }

    public virtual void FillAttributs(IDataRecord rdr)
    {
        this.Id = (int)rdr["EventId"];
        this.ClientId = (int)rdr["ClientId"];
    }
}

public class ControlItem : EventItem
{
    public int ControlId { get; set; }

    public ControlItem(IDataRecord rdr) : base(rdr)
    {
        FillAttributs(rdr);
    }

    public override void FillAttributs(IDataRecord rdr)
    {
        base.FillAttributs(rdr); // Version 1
        this.ControlId = (int)rdr["ControlId"];
    }
}
...
ControlItem ctrl = new ControlItem(rdr)

Version 1 : With base.FillAttributs(rdr), FillAttributs of base class and child class are called twice. Without, only FillAttributs of child class is called twice.

Version 2 : I remove base.FillAttributs(rdr), virtual and replace override with public new void FillAttributs(IDataRecord rdr). So It works but I'm not sure if it's a good practice.

Version 3 : I rename FillAttributs of base class to FillEventAttributs and of chil class to FillControlAttributs.

what is the right way to go here ? Or should I use another way to do it ?


Solution

  • Remove FillAttributs(rdr) from ControlItem constructor. its look like this:

    public class EventItem
    {
    public int Id { get; set; } = -1;
    public int ClientId { get; set; }
    
    public EventItem(IDataRecord rdr)
    {
        FillAttributs(rdr);
    }
    
    public virtual void FillAttributs(IDataRecord rdr)
    {
        this.Id = (int)rdr["EventId"];
        this.ClientId = (int)rdr["ClientId"];
    }
    }
    
    public class ControlItem : EventItem
    {
    public int ControlId { get; set; }
    
    public ControlItem(IDataRecord rdr) : base(rdr)
    {
        //FillAttributs(rdr);
    }
    
    public override void FillAttributs(IDataRecord rdr)
    {
        base.FillAttributs(rdr); // Version 1
        this.ControlId = (int)rdr["ControlId"];
    }
    }
    ...
    ControlItem ctrl = new ControlItem(rdr)
    

    Now base and derived called once. I hope this help you.