C#:从子的构造函数体调用父(Base)构造函数

时间:2018-04-04 19:54:53

标签: c# inheritance constructor

我有一个抽象类Parent和一个派生类Child。我知道我可以通过以下方式在Parent的构造函数中调用Child的构造函数:

abstract class Parent 
{
    protected int i;
    protected Parent(int i) 
    {
        this.i = i;
    }
}

class Child : Parent 
{
    public Child(int i) : base(i) 
    {
    }
}

但是,我不想立即将一些参数传递给Parent构造函数。我想执行一些计算,然后调用Parent的构造函数,使用这样的计算结果作为输入参数。代码“会看起来像这样:

public class Child : Parent 
{
    public Child(int i) 
    {
        int calculation = i * 2; // Complicated operation
        base(calculation); // This line will break
    }
}

第二个片段不是有效的C#代码。有没有办法推迟调用Parent的构造函数来模仿第二个代码片段中表达的情绪?

5 个答案:

答案 0 :(得分:3)

abstract class Parent
{
    protected int i;
    protected Parent(int i)
    {
        this.i = i;
    }

    protected Parent(Func<int> param)
    {
        i = param();
    } 
}

class Child : Parent
{
    public Child(int i) : base(() => i * 2)
    {

    }
}

答案 1 :(得分:2)

创建静态方法并使用base(MyStaticMethod(params))

答案 2 :(得分:2)

如果允许您以这种方式在子类中调用 base 构造函数,则可能会在程序中遇到奇怪的问题。意味着您可以将该实例保持在不一致状态,因为您可以使用try-catch来处理某些输入参数错误并绕过构造函数。这不是主意,想象一下,如果你被允许以这种方式创建一个日期。

class MyDate : DateTime
{
  public int(int year, int month, int day)
  {
      try
     {
        base(-1, -1, -1)
     }
     catch
    {
    }
  }
}

有趣的是,Java允许使用超级关键字。

答案 3 :(得分:2)

假设您可以直接访问属性,这将采用相同的技巧

abstract class Parent 
{
    protected int i;
    protected Parent() 
    {
       //default constructor
    }
}

class Child : Parent 
{
    public Child(int i)
    {

        Int calculation = i * 2
        base.i = calculation
    }
}

但是如果由于对属性的限制访问而无法做到这一点,我个人的偏好是在单独的函数中将计算逻辑外包并调用基类如下:

abstract class Parent 
{
    protected int i;
    protected Parent(int i) 
    {
        this.i = i;
    }
}

class Child : Parent 
{
    public Child(int i) : base(Child.dosomework(i)) 
    {
    }

    public static int dosomework(int i){
        int calculation = i * 2
        return calculation
    }
}

答案 4 :(得分:1)

构造函数的要点是构造实例,即使其进入有效状态。它应该做到这一点,没有别的。如果您的课程在没有设置i的情况下可以存在,那么设置i的行为对其有效性并不重要,因此不属于构造函数。

也许你不想要继承,你想要合成。

class Inner
{
    protected readonly int _i;

    public Inner(int i)
    {
        _i = i;
    }
}

class Outer
{
    protected Inner _inner = null;

    public Outer()
    {
        //Construct
    }

    public void SetI(int i)
    {
        _inner = new Inner(i);  //Call constructor of Inner
    }
}