【问题标题】:use a derived class's field in the base class in c#在 C# 的基类中使用派生类的字段
【发布时间】:2012-07-18 09:31:58
【问题描述】:

我想要一个在基类中定义的字段,它将影响属于该基类的对象的创建。但是,我希望能够覆盖字段的值,基类 cto'r 被调用之前。一个例子:

class ObjNeedParam
{
    public ObjNeedParam(int p)
    {
        val = p;
    }
    int val;
    int Value{get{return Value;}}
}
class Base
{
    public Base()
    {
        obj = new ObjNeedParam(paramVal);
    }
    ObjNeedParam obj;
    protected int paramVal = 1;
}

class Derived : Base
{
    public Derived()
    { 
        //Once I'm here, obj has already been created with paramVal=1 instead of 2!            
        dummy = 3;
    }
    new int paramVal = 2;
    int dummy;
}

【问题讨论】:

  • 将 paramval 设为虚拟属性并覆盖它
  • 您必须将值传递给基本构造函数
  • 我理解问题和答案 - 我不明白的是 2 次投反对票...在这种情况下,你为什么要投反对票而不发表评论?

标签: c# inheritance field derived


【解决方案1】:

这种做法有些可疑,因此您可能需要在此处重新考虑您的方法。

如果您仍想继续这样做,正确的方法是使用virtual 方法,将这个值提供给基础构造函数:

class Base
{
    public Base()
    {
        obj = new ObjNeedParam(GetParamVal());
    }

    protected virtual int GetParamVal() { return 1; }
}

class Derived : Base
{
    protected override int GetParamVal() { return 2; }
}

您必须确保 override 不使用在 Derived 的构造函数中初始化的 Derived 的任何类成员,因为该构造函数尚未在调用覆盖的点!见Virtual member call in a constructor

更新:这有点值得怀疑,因为在构造某个派生类型的对象时,编译器有一个问题要解决:应该以什么顺序初始化字段和构造函数运行,以便任何方法调用从任何构造函数内部都可以保证找到处于“可用”状态的对象?

这个问题在一般情况下无法解决,因为根据定义,直到所有构造函数都返回后,对象才处于可用状态,我们正在讨论从这些构造函数内部调用方法。因此,编译器必须尽可能地保证,并防止或允许您做无法证明安全的事情。

在这种情况下,C++(有趣地)阻止了无法证明安全的事情,而 C# 允许这样做。因此,这有点值得怀疑,因为如果您不注意,可能会引入错误。更安全的方法是编写类,以便在构造函数运行后初始化该成员。

【讨论】:

  • 太棒了,这行得通!但是,请您详细说明“有些问题”吗?如果这不是正确的方法,我很想知道为什么。谢谢!
  • @zorbar:更新了答案,看看吧。
  • 我明白了。非常感谢详细的解释。
【解决方案2】:

您需要做的是以这种方式初始化字段。一种替代方法是将字段设为属性,并允许由子类覆盖。或者,允许通过参数在基类构造函数中设置字段,这样您就可以编写如下代码:

class Base
{
    public Base() : this(1)
    {
    }

    public Base(int param)
    {
        paramVal = param;
    }

    private int paramVal;
}

class Derived : Base
{
    public Derived() : base(2)
    {   
    }
}

最终,一个字段通常是私有类的,并且永远不能被派生类覆盖。如果您想公开它以供派生类操作,那么您可能需要字段以外的东西。

【讨论】:

    猜你喜欢
    • 2010-11-22
    • 2011-08-16
    • 2013-08-16
    • 2018-05-19
    • 2015-02-25
    • 1970-01-01
    • 2018-01-20
    • 2017-07-04
    • 2019-07-25
    相关资源
    最近更新 更多