【发布时间】:2012-02-28 14:35:16
【问题描述】:
我刚刚在阅读 C# 中的继承时遇到了构造函数,并写到 构造函数按派生顺序执行。 这是什么意思?将首先调用基类构造函数或派生类。
【问题讨论】:
-
是的,基类对象必须在派生类对象之前构造。
我刚刚在阅读 C# 中的继承时遇到了构造函数,并写到 构造函数按派生顺序执行。 这是什么意思?将首先调用基类构造函数或派生类。
【问题讨论】:
using System;
class Parent
{
public Parent () {
Console.WriteLine("Hey Its Parent.");
}
}
class Derived : Parent
{
public Derived () {
Console.WriteLine("Hey Its Derived.");
}
}
class OrderOfExecution {
static void Main() {
Derived obj = new Derived();
}
}
此程序的输出如下所示:
嘿它的父母。
嘿,它是派生的。
构造函数在继承方面的行为不同,对于新程序员来说有点混乱。构造函数的执行有两个概念 1。打电话 2. 执行 当您创建名为 Derived 的派生类的对象时,构造函数首先转到 Derived(),然后由于调用它而转到 Parent()。 构造函数调用是从下到上完成的,但是你发现它先执行 Parent() 然后 Derived ,这是因为它的执行。 构造函数从上到下执行。这就是为什么它首先打印 Parent 然后 Base 而 base 构造函数首先调用。
【讨论】:
类构造函数按派生隐含的顺序调用,但重要的是要注意,在 C# 中,字段初始值设定项(例如 int foo=5)在基类构造函数之前运行,因此以相反的顺序运行。如果基构造函数可能导致在基构造函数完成之前调用在派生类中被覆盖的虚函数,这主要是有用的。这样的函数会将由字段初始化程序初始化的所有变量都视为已初始化。
VB.net 顺便说一句,在基类构造函数完成后运行所有字段初始化程序,但在派生类构造函数中的任何内容之前(除了指向基构造函数的链)。这意味着虚拟方法必须知道字段初始化程序可能尚未运行,但也意味着字段初始化程序可以使用正在构造的对象(它们在 C# 中不能这样做)。
顺便说一句,在 VB.net 中,虽然很笨拙,但类可以使用新创建的 IDisposable 实例安全地初始化字段(并确保在构造过程的任何部分引发异常时它们将被释放)。在 C# 中,必须避免使用字段初始值设定项来创建任何在构造引发异常时无法安全放弃的内容,因为无法访问部分构造的对象来清理它。
【讨论】:
先调用一个基类Constructor。参考下面的例子
// Demonstrate when constructors are called.
using System;
// Create a base class.
class A {
public A() {
Console.WriteLine("Constructing A.");
}
}
// Create a class derived from A.
class B : A {
public B() {
Console.WriteLine("Constructing B.");
}
}
// Create a class derived from B.
class C : B {
public C() {
Console.WriteLine("Constructing C.");
}
}
class OrderOfConstruction {
static void Main() {
C c = new C();
}
}
The output from this program is shown here:
Constructing A.
Constructing B.
Constructing C.
【讨论】:
将首先调用基类构造函数。您可以自己轻松测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DerivationTest
{
class Program
{
public class Thing
{
public Thing()
{
Console.WriteLine("Thing");
}
}
public class ThingChild : Thing
{
public ThingChild()
{
Console.WriteLine("ThingChild");
}
}
static void Main(string[] args)
{
var tc = new ThingChild();
Console.ReadLine();
}
}
}
【讨论】: