C# 中的继承:如何调用基类构造函数(完整指南)

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么基类构造函数不仅仅是“枯燥的理论”?

\n\n

想象一下你在建造一栋房子。你有一个地基(基类)和房子本身(派生类)。地基已经打好,但要让房子稳固,你需要正确地将它与地基“连接”起来。在 C# 中,这种“连接”是通过 base 关键字调用基类构造函数来实现的。

\n\n

这是 Stack Overflow 上引发数千个问题的主题之一。为什么?因为如果不理解这一机制,你的代码要么无法编译,要么会以不可预测的方式运行。在本文中,我们将从简单到复杂,详细讲解 C# 中基类构造函数的调用:包括示例、陷阱和实际场景。

\n\n

您将从本文中学到什么?

\n
    \n
  • C# 中构造函数继承的工作原理。
  • \n
  • 何时以及为何需要显式调用 base()。
  • \n
  • 如何向基类构造函数传递参数。
  • \n
  • 典型错误及其避免方法。
  • \n
  • 高级技巧:构造函数链和重载。
  • \n
\n\n

1. 基础:什么是基类构造函数?

\n\n

在 C# 中,每个类可以有一个或多个构造函数。当你创建派生类的实例时,首先会调用基类的构造函数。这确保了“父类”的所有字段和属性在“子类”开始工作之前被初始化。

\n\n

如果你没有显式指定要调用哪个基类构造函数,编译器会尝试调用默认构造函数(无参数)。如果不存在这样的构造函数,你将收到编译错误。

\n\n

示例 1:隐式调用(一切简单)

\n
public class Animal\n{\n    public string Name { get; set; }\n\n    public Animal()\n    {\n        Name = "未知动物";\n        Console.WriteLine("Animal: 无参数构造函数");\n    }\n}\n\npublic class Dog : Animal\n{\n    public Dog()\n    {\n        Console.WriteLine("Dog: 构造函数");\n    }\n}\n\n// 使用\nDog dog = new Dog();\n// 输出:\n// Animal: 无参数构造函数\n// Dog: 构造函数
\n\n

这里,Dog 隐式调用了 Animal()。一切正常,因为 Animal 有一个默认构造函数。

\n\n

2. 问题:当没有默认构造函数时

\n\n

现在想象一下,基类需要必需的参数。例如,动物必须有一个名字。如果移除无参数构造函数,代码将无法编译。

\n\n

示例 2:编译错误

\n
public class Animal\n{\n    public string Name { get; }\n\n    public Animal(string name) // 唯一的构造函数\n    {\n        Name = name;\n    }\n}\n\npublic class Dog : Animal\n{\n    // 错误 CS7036:"Animal" 不包含接受 0 个参数的构造函数\n    public Dog() \n    {\n    }\n}
\n\n

编译器会报错:“嘿,我不知道如何在没有名字的情况下初始化 Animal!”。解决方案是使用 base 显式调用基类构造函数。

\n\n

3. base 关键字:显式调用构造函数

\n\n

在 C# 中,base 关键字用于访问基类的成员。在构造函数上下文中,它允许你指定要调用父类的哪个构造函数以及传递哪些参数。

\n\n

语法:

\n
public class 派生类 : 基类\n{\n    public 派生类(参数) : base(参数)\n    {\n        // 构造函数体\n    }\n}
\n\n

冒号和 base(参数) 放在构造函数签名之后、函数体之前。

\n\n

示例 3:修复错误

\n
public class Animal\n{\n    public string Name { get; }\n\n    public Animal(string name)\n    {\n        Name = name;\n        Console.WriteLine($"Animal: 已创建 {name}");\n

博客

书籍推荐