鉴于代码:
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
的构造函数被击中
答案 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