2

给定代码:

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的构造函数会被击中

4

5 回答 5

8

如果您不包含任何base(..)or this(..),它的作用与您包含 相同base()。从C# 规范


如果实例构造函数没有构造函数初始化器,base()则隐式提供表单的构造器初始化器。因此,形式的实例构造函数声明

C(...) {...}

完全等同于

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

您可能一直在寻找,因此您无法直接A创建.abstract classA

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
}
于 2013-09-17T14:11:19.283 回答
1

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

于 2013-09-17T14:10:24.990 回答
1

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

例如

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

    }
}
于 2013-09-17T14:11:03.913 回答
1

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

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

public abstract class A {}

使用该语法,如果您尝试构造 A(但 B 可以),这将是编译时错误,因此您可以删除 A 的构造函数中的 throw。

于 2013-09-17T14:13:28.060 回答
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
于 2013-09-17T14:12:13.073 回答