C# 构造函数
第 1 部分仅介绍了类构造函数的基础知识。 在本课中,我们将详细讨论各种类型的构造函数。
属性类型
- 默认构造函数
- 构造函数重载
- 私有构造函数
- 构造函数链
- 静态构造函数
- 析构函数
请注意构造函数的一些基本概念,并确保你的理解非常清楚,否则你无法理解 OOP(构造函数)。
- 构造函数的名称与类名相同。
- 构造函数的目的是为了初始化成员变量。
- 创建对象时会自动调用构造函数。
- 构造函数没有任何返回类型,甚至没有 void。
- 如果我们希望自动执行某些代码,那么我们想要执行的代码必须放在构造函数中。
- 我们不能明确调用构造函数。
C# 构造函数的一般形式如下。
modifier constructor_name(parameters)
{
// constructor body
}
修饰符可以是 private、public、protected 或 internal。构造函数的名称必须是其定义所属类的名称。构造函数可以接受零个或多个参数。零个参数(即无参数)的构造函数称为默认构造函数。请记住,构造函数没有返回类型。
默认构造函数
无参数的构造函数称为默认构造函数。请记住,构造函数没有返回类型。默认构造函数只是调用直接基类的无参数构造函数。
例子
using System;
namespace DefaultConstructors
{
class Program
{
static void Main(string[] args)
{
// 创建 car 类的一个实例 sportscar,调用默认构造函数
car sportscar = new car();
// 打印 sportscar 的 model_Id 属性值
Console.WriteLine("Car Model is :{0} ", sportscar.model_Id);
// 打印 sportscar 的 Maker_Name 属性值
Console.WriteLine("Car Name is :{0}", sportscar.Maker_Name);
// 等待用户按下任意键继续执行程序
Console.ReadKey();
}
// 定义 car 类
class car
{
// 私有字段 model,表示车型
private int model = -1;
// 私有字段 maker,表示制造商
private string maker = string.Empty;
// 默认构造函数
public car()
{
// 默认构造函数的主体是空的,可以添加初始化逻辑
}
// 公共只读属性 model_Id,用于获取 model 字段的值
public int model_Id
{
get
{
return model;
}
}
// 公共只读属性 Maker_Name,用于获取 maker 字段的值
public string Maker_Name
{
get
{
return maker;
}
}
}
}
}
输出
在这个简单的例子中,我们有一个无参数或零参数的构造函数,它是类的默认构造函数。上述示例的输出是空成员变量。
请注意另外一点;如果我们从示例 1 中删除以下代码,则输出是相同的。
public car()
{
//Default Constructor
}
这意味着如果我们没有定义类的构造函数,系统将调用默认构造函数。
构造函数重载
首先,我们来讨论一下构造函数重载的目的;对前面的主题有清晰的理解非常重要。在设计 OOP 模型时存在许多复杂的情况,我们需要为类的不同目的初始化一组不同的成员变量。所以我们需要使用构造函数重载。构造函数重载的定义是。
和成员函数一样,构造函数也可以在类中重载。重载的构造函数必须在参数数量和/或参数类型和/或参数顺序上有所不同。
例子
using System;
namespace ConstructorsOverloading
{
class Program
{
static void Main(string[] args)
{
// 使用无参数构造函数创建 car 类的一个实例
car sportscar1 = new car();
// 使用包含两个参数(model 和 maker)的构造函数创建 car 类的一个实例
car sportscar2 = new car(2013, "mercedes");
// 使用包含两个参数(maker 和 Enginetype)的构造函数创建 car 类的一个实例
car sportscar3 = new car("mercedes", 7.8);
// 输出使用无参数构造函数创建的 sportscar1 的属性值
Console.WriteLine("Constructor without arguments");
Console.WriteLine("Car Model is :{0} ", sportscar1.model_Id);
Console.WriteLine("Car Name is :{0}", sportscar1.Maker_Name);
Console.WriteLine("Car Engine Power is :{0}", sportscar1.Engine);
// 输出使用包含两个参数的构造函数创建的 sportscar2 的属性值
Console.WriteLine("\nConstructor with two arguments");
Console.WriteLine("Car Model is :{0} ", sportscar2.model_Id);
Console.WriteLine("Car Name is :{0}", sportscar2.Maker_Name);
Console.WriteLine("Car Engine Power is :{0}", sportscar2.Engine);
// 输出使用包含两个参数的构造函数创建的 sportscar3 的属性值
Console.WriteLine("\nConstructor with two arguments");
Console.WriteLine("Car Model is :{0} ", sportscar3.model_Id);
Console.WriteLine("Car Name is :{0} ", sportscar3.Maker_Name);
Console.WriteLine("Car Engine Power is :{0}", sportscar3.Engine);
// 等待用户按下任意键继续执行程序
Console.ReadKey();
}
// 定义 car 类
class car
{
// 私有字段,表示车型
private int model = -1;
// 私有字段,表示制造商
private string maker = string.Empty;
// 私有字段,表示发动机类型
private double Enginetype = 0.0;
// 无参数的默认构造函数
public car()
{
// 默认构造函数的主体是空的,可以添加初始化逻辑
}
// 包含两个参数(model 和 maker)的构造函数
public car(int _model, string _maker)
{
model = _model;
maker = _maker;
}
// 包含两个参数(maker 和 Enginetype)的构造函数
public car(string _maker, double _power)
{
maker = _maker;
Enginetype = _power;
}
// 公共属性,用于获取和设置 model 字段的值
public int model_Id
{
get
{
return model;
}
set
{
model = value;
}
}
// 公共属性,用于获取和设置 maker 字段的值
public string Maker_Name
{
get
{
return maker;
}
set
{
maker = value;
}
}
// 公共属性,用于获取和设置 Enginetype 字段的值
public double Engine
{
get
{
return Enginetype;
}
set
{
Enginetype = value;
}
}
}
}
}
输出
亲爱的读者,请注意,在这个例子中,我们使用三个不同的对象重载了构造函数,它们是sportscar1、sportscar2 和 sportscar3。
我们注意到
- sportscar1 没有参数(默认构造函数超出了主题范围)。因此该成员变量具有在初始化时分配的默认值。
- sportscar2 有两个参数,分别用值 2013 和 Mercedes 初始化成员变量 model 和 name,但没有初始化 Enginetype 变量,因此它具有默认值零。
- sportscar3 有两个参数,分别用值 Mercedes 和 7.8 初始化成员变量 name 和 Enginetype,但不初始化 model 变量,因此它具有默认值 -1。
私有构造函数
亲爱的读者,我们知道,私有访问修饰符有点特殊。我们既不能创建类的对象,也不能仅使用私有构造函数来继承类。但是,是的,我们可以在类中拥有一组公共构造函数以及私有构造函数,并且公共构造函数可以通过构造函数链从类内部访问私有构造函数。私有构造函数通常用于仅包含静态成员的类中。
using System;
namespace PrivateConstructors
{
class Program
{
static void Main(string[] args)
{
// 使用包含 model 参数的构造函数创建 car 类的一个实例
car sportscar = new car(2013);
Console.Read();
}
class car
{
// 公共字段,表示汽车名称
public string carname;
// 私有的默认构造函数
private car()
{
// 初始化 carname 字段
carname = "lamborghini";
}
// 公共的构造函数,包含一个 int 型的 model 参数
// 该构造函数通过 :this() 调用私有的默认构造函数
public car(int model) : this()
{
// 打印车型年份
Console.WriteLine("Model Year:{0}", model);
// 打印制造商名称
Console.WriteLine("Maker Name:{0}", carname);
}
}
}
}
这是一个非常简单的私有构造函数的例子,其中我们使用公共构造函数来调用私有构造函数。
构造函数链
亲爱的读者,当一个构造函数调用同一个类或该类的基类中的另一个构造函数时,这被称为构造函数链。这是避免代码重复的非常有用的技术。
using System;
namespace Constructorchaining
{
class Program
{
static void Main(string[] args)
{
// 使用包含 engine 参数的构造函数创建 car 类的一个实例
car sportscar = new car(7.8);
Console.Read();
}
class car
{
// 公共字段,表示汽车名称
public string carname;
// 公共字段,表示车型年份
public int model;
// 公共字段,表示发动机类型
public double engine;
// 包含一个 carname 参数的构造函数
public car(string _carname)
{
carname = _carname;
}
// 包含一个 model 参数的构造函数,并调用包含 carname 参数的构造函数
public car(int _model) : this("lamborghini")
{
model = _model;
}
// 包含一个 engine 参数的构造函数,并调用包含 model 参数的构造函数
public car(double _engine) : this(2013)
{
engine = _engine;
// 打印车型年份
Console.WriteLine("Model Year:{0}", model);
// 打印制造商名称
Console.WriteLine("Maker Name:{0}", carname);
// 打印发动机类型
Console.WriteLine("Engine Type:{0}", engine);
}
}
}
}
在前面的例子中,我们创建了三个不同的类,它们都具有相同的名称 car 和不同的参数类型,每个类都链接前一个类来调用另一个构造函数。
静态构造函数
静态构造函数是一种特殊类型,不采用访问修饰符,也不具有参数。在创建第一个实例或引用任何静态成员之前,会自动调用它以初始化类。静态构造函数不会被直接调用。用户无法控制静态构造函数的执行。
using System;
namespace staticconstructors
{
class Program
{
// 定义 car 类
public class car
{
// 静态构造函数
static car()
{
// 打印静态信息,静态构造函数在类第一次被使用前自动调用,并且只调用一次
System.Console.WriteLine(@"Lamborghini is the best sports car owned by Audi AG 1998 (its static info)");
}
// 静态方法 Drive
public static void Drive()
{
// 打印稳定公司信息
System.Console.WriteLine("Audi is the stable company");
}
}
// 主程序入口点
static void Main()
{
// 调用 car 类的静态方法 Drive
car.Drive();
// 再次调用 car 类的静态方法 Drive
car.Drive();
// 等待用户按下任意键继续执行程序
Console.ReadKey();
}
}
}
输出
注意,静态构造函数在第一次加载类时被调用。当我们再次调用“car.Drive”时,它不会调用静态构造函数。
析构函数
亲爱的读者,当我们使用 OOP 并在系统内存中创建对象时,需要从系统内存中清除不需要的对象。.NET 框架内置了垃圾收集功能,用于释放未使用对象占用的内存。析构函数是一个与类名同名但以字符 ~ 开头的函数。析构函数不能有任何修饰符 private、public 等。
例子
class car
{
// 公共构造函数
public car()
{
// 构造函数,在创建对象实例时调用
// 可以在这里进行对象的初始化操作
// 比如分配资源,设置初始状态等
}
// 析构函数
~car()
{
// 析构函数,在对象被垃圾回收时调用
// 可以在这里进行对象的清理操作
// 比如释放资源,关闭文件,断开网络连接等
}
}