【问题标题】:Base Virtual Method not called or called twice基本虚拟方法未调用或调用两次
【发布时间】:2017-11-16 14:41:29
【问题描述】:

这是我的代码。

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)

版本 1 :基类和子类的base.FillAttributs(rdr)FillAttributs 被调用两次。没有的话,只会调用子类的FillAttributs 两次。

版本 2:我删除了 base.FillAttributs(rdr)virtual 并将 override 替换为 public new void FillAttributs(IDataRecord rdr)。所以它有效,但我不确定这是否是一个好习惯。

版本 3:我将基类的 FillAttributs 重命名为 FillEventAttributs,将 chil 类的重命名为 FillControlAttributs

去这里的正确方法是什么?还是我应该使用其他方式来做到这一点?

【问题讨论】:

  • 这背后的原因是构造函数。当您创建ControlItem 的对象时,首先调用基本构造函数,然后调用ControlItem 的构造函数。他们都调用 FillAttributs 方法,这就是为什么你会看到他们被调用了两次。
  • 它们被调用了两次,因为您在每个的构造函数中都有一个调用 FillAttributes()。如果您只想调用一次,请将其排除在构造函数之外并根据需要填充它们。
  • 这取决于当有人从类外调用FillAttributes 时您想要什么功能。

标签: c# inheritance overriding virtual method-hiding


【解决方案1】:

从 ControlItem 构造函数中删除 FillAttributs(rdr)。 它看起来像这样:

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)

现在基和派生调用一次。 希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多