2012-07-27 102 views
1

给定下面的两个类,我想用int参数调用Child构造函数,然后用int参数调用父构造函数,最后使用Child无参数构造函数。C#构造器链接

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

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 Go如果“学习练习要以最少的代码遵循DRY方法。正常模式是在类中使用一个内部私有函数,该函数具有从每个构造函数执行的通用代码。

编辑2

我加的例子生产代码。

+2

你只能一次链,并且可以”从父母到孩子的连锁。 – Oded 2012-07-27 18:14:28

+1

你想在类的构造过程中调用同一个类的多个构造函数吗?我认为你甚至不会**那样做。如果你解释为什么你想这样做,我相信我们可以帮助你想出一个不同的解决方案。 – 2012-07-27 18:14:37

+0

@Oded你错了,**可以**多于一个链接调用(例如'Child():this(1)'和'Child(int val):base(val)'将有效地导致跟随来电订购:'父(INT),儿童(INT),儿童()' – 2012-07-27 18:17:21

回答

2

不,您不能这样做,因为您不能从Parent调用Child构造函数。

0

Inheritance只能作为一种方式。

Child --->Parent

你可能有一个结构错误,因为(有人纠正我,如果我错了)不存在情况下,您会必须调用同一类的两个构造驯服时间。

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

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."); 
    } 
} 
+0

这是我们用来保持DRY的正常模式。 – Sam 2012-07-27 18:27:46

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"); 
    } 
} 
+0

是的,这和我下面的第二个可能的答案是一样的。 – 2012-07-27 20:00:06

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)"); 
    } 
} 
+0

希望这些可以帮助你。我正在收藏这本书,因为我很好奇看到你想出什么。可以肯定的是,这是一个奇怪的问题。 – 2012-07-27 18:42:23

+0

在最后一个例子中,我认为静态变量在调用Child无参数构造函数之前不会被设置。你测试过了吗? – Sam 2012-07-27 19:06:35

+0

哈哈......你说得对。无论哪种方式,我认为你无论如何都无法得到你想要的订单,因为它不会首先执行子控制器。父母将始终开火。 – 2012-07-27 19:56:25