Base Classes构造函数在没有调用的情况下被命中?

时间:2013-09-17 14:07:44

标签: c# oop

鉴于代码:

public class A
{
    public A()
    {
        throw new Exception();
    }
}

public class B : A
{
    public B(int i)
    {

    }
}

然后运行该行:

  var x = new B(2);

我永远不会指望A的构造函数被命中(除非我将base()添加到B的构造函数声明的末尾。

奇怪的是它似乎被击中(并抛出异常)。这是默认行为吗?这让我感到震惊,因为我完全没想到要A的构造函数被击中

5 个答案:

答案 0 :(得分:8)

如果您不包含任何base(..)this(..),那么就像使用base()一样。来自C# spec


如果实例构造函数没有构造函数初始值设定项,则隐式提供形式为base()的构造函数初始值设定项。因此,形式

的实例构造函数声明
C(...) {...}

完全等同于

C(...): base() {...}

您可能一直希望A成为abstract class,这样您就无法直接创建A的实例。

public abstract class A
{
}

public class B : A
{
    public B(int i)
    {

    }
}

public static void Main()
{
    // A a = new A(); // doesn't compile
    A a = new B(2); // valid
}

答案 1 :(得分:1)

但是在A类继承的B类中。当你在B实例上创建时,也会自动启动A实例。这是OOP概念中的默认行为。

答案 2 :(得分:1)

这是默认行为。构造函数按顺序从基类开始到最后继承的类。当你编写base()时,你可以将一些值直接传递给基础构造函数

例如

public class B : A
{
    public B(int i): base(i)
    {

    }
}

答案 3 :(得分:1)

正如您的评论员所提到的,这是默认的C#行为。必须调用每个基类的构造函数。

如果你的规则是永远不应该构造ClassA(只有子类),则将ClassA声明为抽象

public abstract class A {}

使用该语法,如果您尝试构造A(但B可以正常),则会出现编译时错误,因此您可以删除A的构造函数中的throw。

答案 4 :(得分:0)

这是预期的:如果您没有明确指定构造函数的不同重载,则默认情况下将始终调用它。即使你确实指定了一个不同的重载来调用,它也会传播到它的基类的构造函数,直到它到达根Object()构造函数。

请注意,这也意味着如果在单个类中有不同的构造函数重载,通过重载构造函数实例化对象将调用同一类的无参数构造函数,而是无参数基类的构造函数(在本例中为Object()):

public class A
{
    public A()
    {
        throw new Exception();
    }

    public A(int i)
    {
        // this will not call the A(), but the base Object() constructor
    }
}

var a = new A(5); // no exception thrown