C#构造函数链接

时间:2012-07-27 18:12:56

标签: c# constructor

鉴于下面的两个类,我想使用int参数调用Child构造函数,然后使用int参数调用父构造函数,并使用Child无参数构造函数。

这可以在不使用可选参数的情况下完成吗?

public class Parent
{
    public Parent()
    {
        Console.WriteLine("Parent ctor()");
    }

    public Parent(int i)
    {
        Console.WriteLine("Parent ctor(int)");
    }
}

public class Child:Parent
{
    public Child()
    {
        Console.WriteLine("Child ctor()");
    }

    public Child(int i)
    {
        Console.WriteLine("Child ctor(int)");
    }
}

这是.NET 4中我们想要在.NET 2.0中实现的逻辑

public class Parent2
{
    public Parent2(int? i = null)
    {
        Console.WriteLine("Parent2 ctor()");

        if (i != null)
        {
            Console.WriteLine("Parent2 ctor(int)");

        }
    }
}

public class Child2 : Parent2
{
    public Child2(int? i = null)
        : base(i)
    {
        Console.WriteLine("Child2 ctor()");

        if (i != null)
        {
            Console.WriteLine("Child2 ctor(int)");
        }
    }
}

以下是我们讨论的生产代码

public class DataPoint<T>
{
    public DataPoint() { }

    public DataPoint(T xValue, int yValue)
    {
        XAxis = xValue;
        YAxis = yValue;
    }

    public T XAxis { get; set; }
    public int YAxis { get; set; }
}

public class DataPointCollection<T> : DataPoint<T>
{
    DataPointCollection()
    {
        Labels = new List<string>();
    }

    DataPointCollection(T xValue, int yValue)
        : base(xValue, yValue)
    { }

    public List<string> Labels { get; set; }
}

修改

此时问题的原因是“Code Golf”学术练习以最少的代码遵循DRY方法。正常模式是在类中使用内部私有函数,该函数具有从每个构造函数执行的公共代码。

编辑2

我添加了示例生产代码。

5 个答案:

答案 0 :(得分:2)

不,您不能这样做,因为您无法从Child致电Parent构造函数。

答案 1 :(得分:1)

如果您需要一系列初始化方法,我建议您将它们定义为 - 正常(非构造函数)方法。您可以使用可覆盖的受保护方法来设置来回,因为构造函数可以选择以任何组合或顺序调用哪些初始化方法:

public class Parent {

    public Parent() { }

    public Parent(int i) {
        initWithArg(i);
        initNoArgs();
    }

    virtual protected void initWithArg(int i) {
        Console.WriteLine("Parent initWithArg(int)");
    }

    virtual protected void initNoArgs() {
        Console.WriteLine("Parent initNoArgs");
    }
}

public class Child : Parent {

    // Override the *parameterless* constructor
    public Child(int i) : base() {
        initWithArg(i);
        base.initWithArg(i);
        initNoArgs();
    }

    override protected void initWithArg(int i) {
        Console.WriteLine("Child initWithArg(int)");
    }

    override protected void initNoArgs() {
        Console.WriteLine("Child initNoArgs");
    }
}

答案 2 :(得分:0)

Inheritance仅适用于单向。

Child ---&gt; Parent

你可能有一个结构错误,因为(有人纠正我,如果我错了)没有任何情况你必须在温和的时候调用同一个类的两个构造函数。

除了递归构造函数,因为它调用自身,所以它不是一回事。

答案 3 :(得分:0)

您可以通过定义Child(int i)构造函数来完成问题的第一部分:

public Child(int i) : base(i)
{
    Console.WriteLine("Child ctor(int)");
}

但是,如上所述,您无法随后调用另一个Child的构造函数。如果您的实际目标(假设这不是一个纯粹的学术问题)是确保Child的默认构造函数中包含的某些标准行为始终执行,那么最好将其封装在一个方法并从Child的每个构造函数中调用它:

public class Child:Parent
{
    public Child()
    {
        Console.WriteLine("Child ctor()");
        CommonChildConstructionBehaviour();
    }

    public Child(int i) : base(i)
    {
        Console.WriteLine("Child ctor(int)");
        CommonChildConstructionBehaviour();
    }

    private void CommonChildConstructionBehaviour()
    {
        Console.WriteLine("All child constructors must call me.");
    }
}

答案 4 :(得分:0)

有一些选择,但没有一个是完美的。最后,我的主要建议是升级到.NET 4.0,如果可以的话(显然)。

这是一个选项,使用一个对象,然后将其转换为你需要的内容。这是明显的缺点,因为你将失去打字或打破签名,但它可能适合你的情况,我不知道:

public class Parent3
{
    public Parent3(object i)
    {
        Console.WriteLine("Parent3 ctor()");

        if (i != null)
        {
            Console.WriteLine("Parent3 ctor(int)");
        }
    }
}

public class Child3 : Parent3
{
    public Child3(object i)
        : base(i)
    {
        Console.WriteLine("Child3 ctor()");

        if (i != null)
        {
            Console.WriteLine("Child3 ctor(int)");
        }
    }
}

这是另一种选择,使用Init方法。但是,它们不会以完全相同的顺序触发,但它可能适合您。

    public class Parent
{
    public Parent()
    {
        Init();
    }

    protected void Init()
    {
        Console.WriteLine("Parent ctor()");
    }

    public Parent(int i)
    {
        Init(i);
    }

    protected void Init(int i)
    {
        Console.WriteLine("Parent ctor(int)");
    }
}

public class Child : Parent
{
    public Child()
    {
        Init();
    }

    protected void Init()
    {
        Console.WriteLine("Child ctor()");
    }

    public Child(int i)
    {
        Init(i);
        base.Init(i);
        Init();
    }


    protected void Init(int i)
    {
        Console.WriteLine("Child ctor(int)");
    }

}

然后这是你可以做到的一种我真的不推荐的方式,但无论如何我都会把它包括在内

    public class Parent
{
    public Parent()
    {
        Console.WriteLine("Parent ctor()");
    }

    public Parent(int i)
    {
        Console.WriteLine("Parent ctor(int)");
    }
}

public class Child : Parent
{
    private static int _i; //this is likely to blow up at some point.

    public Child() : base(_i)
    {
        Console.WriteLine("Child ctor()");
    }

    public Child(int i) : this()
    {
        _i = i;
        Console.WriteLine("Child ctor(int)");
    }
}