VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 构造函数与析构函数

构造函数与析构函数

  1. 构造函数
    构造函数是类的特殊方法,用于初始化对象,与类名完全一致,无返回值(连void都不能写)。它在对象创建vb.net教程C#教程python教程SQL教程access 2010教程时自动调用,确保对象处于合法初始状态。
    1.1 默认构造函数
    若类未显式定义构造函数,编译器会自动生成无参数的默认构造函数,用于初始化字段为默认值(如int为0,string为null)。
    实例:
    csharp
	public class Person
	{
	// 私有字段
	private string _name;
	private int _age;
	
	// 未显式定义构造函数 → 编译器自动生成默认构造函数
	}
	
	// 使用
	Person p = new Person(); 
	// 默认构造函数将_name初始化为null,_age初始化为0

注意:若显式定义了带参构造函数,编译器不再生成默认构造函数。如需无参构造,需手动添加:
csharp

	public class Person
	{
	private string _name;
	private int _age;
	
	// 显式定义无参构造函数
	public Person() 
	{
	_name = "未知";
	_age = 18; // 设置默认年龄
	}
	
	// 带参构造函数
	public Person(string name, int age)
	{
	_name = name;
	_age = age;
	}
	}

1.2 自定义构造函数
自定义构造函数通过参数传递初始化对象,直接给私有字段赋值,避免创建对象后多次调用属性赋值。
实例:
csharp

	public class Person
	{
	private string _name;
	private int _age;
	
	// 自定义构造函数:带name和age参数
	public Person(string name, int age)
	{
	// 用参数初始化字段(参数名与字段名不同,无需this)
	_name = name;
	_age = age;
	}
	
	// 公共方法:输出信息
	public void Introduce()
	{
	Console.WriteLine($"我是{_name},今年{_age}岁");
	}
	}
	
	// 使用
	Person p = new Person("张三", 25); 
	p.Introduce(); // 输出:我是张三,今年25岁

逐行讲解:
public Person(string name, int age):构造函数名与类名一致,参数name和age用于接收初始化值。
_name = name:将参数name赋值给私有字段_name,确保对象创建时就有合法姓名。
new Person("张三",25):创建对象时,构造函数自动调用,完成初始化。
1.3 构造函数重载
构造函数支持重载(多个构造函数,参数数量/类型不同),实现多种初始化方式。
实例:
csharp

	public class Person
	{
	private string _name;
	private int _age;
	
	// 重载1:无参构造(默认值)
	public Person()
	{
	_name = "未知";
	_age = 18;
	}
	
	// 重载2:仅姓名参数(年龄默认20)
	public Person(string name)
	{
	_name = name;
	_age = 20;
	}
	
	// 重载3:姓名+年龄参数
	public Person(string name, int age)
	{
	_name = name;
	_age = age;
	}
	
	public void Introduce()
	{
	Console.WriteLine($"我是{_name},今年{_age}岁");
	}
	}
	
	// 使用
	Person p1 = new Person(); // 调用重载1 → 未知,18
	Person p2 = new Person("李四"); // 调用重载2 → 李四,20
	Person p3 = new Person("王五",30); // 调用重载3 → 王五,30

规则:重载构造函数的参数必须满足数量不同或类型不同(顺序不同也算,但不推荐,易混淆)。
1.4 this关键字:解决参数与字段重名
若构造函数参数名与字段名相同,需用this关键字指代当前对象的字段,避免歧义。
实例:
csharp

	public class Person
	{
	private string _name;
	private int _age;
	
	// 参数名与字段名相同 → 用this区分
	public Person(string name, int age)
	{
	this._name = name; // this._name → 当前对象的_name字段
	this._age = age;
	}
	}

1.5 静态构造函数
静态构造函数用static修饰,用于初始化静态成员(类级别的数据,所有对象共享)。
核心特性:
无参数,只能有一个;
类第一次被使用时自动调用一次(不管创建多少对象);
无法手动调用。
实例:
csharp

	public class Person
	{
	// 静态字段:记录创建的对象总数
	public static int TotalCount;
	
	// 静态构造函数:初始化静态字段
	static Person()
	{
	TotalCount = 0;
	Console.WriteLine("静态构造函数被调用");
	}
	
	// 实例构造函数:每次创建对象时自增总数
	public Person()
	{
	TotalCount++;
	Console.WriteLine($"实例构造函数被调用,当前总数:{TotalCount}");
	}
	}
	
	// 使用
	Person p1 = new Person(); 
	// 输出:静态构造函数被调用 → 实例构造函数被调用,当前总数:1
	Person p2 = new Person(); 
	// 输出:实例构造函数被调用,当前总数:2(静态构造函数不再调用)
  1. 析构函数
    析构函数(Finalize方法)用于释放对象占用的非托管资源(如文件句柄、数据库连接、Win32 API分配的内存)。它由垃圾回收器(GC)自动调用,执行时机不确定。
    2.1 语法与实例
    析构函数用~+类名定义,无参数、无访问修饰符、无返回值。
    实例:释放文件资源
    csharp
	public class FileHandler
	{
	private FileStream _stream;
	
	// 构造函数:打开文件
	public FileHandler(string filePath)
	{
	_stream = new FileStream(filePath, FileMode.Open);
	Console.WriteLine("文件已打开");
	}
	
	// 析构函数:释放文件资源
	~FileHandler()
	{
	if (_stream != null)
	{
	_stream.Close();
	Console.WriteLine("析构函数释放文件资源");
	}
	}
	}
	
	// 使用
	FileHandler fh = new FileHandler("test.txt");
	fh = null; // 让对象成为GC回收目标
	GC.Collect(); // 强制GC回收(仅测试用,实际不推荐)
	GC.WaitForPendingFinalizers(); // 等待析构函数执行
	// 输出:析构函数释放文件资源

2.2 局限性
析构函数的执行时机完全由GC决定,可能延迟很久才执行,甚至程序退出前都不执行。因此:
不推荐依赖析构函数释放资源;
仅用于释放非托管资源(托管资源由GC自动回收);
无法手动调用。
3. 基础知识拓展
3.1 构造函数执行顺序
静态构造函数 → 父类实例构造函数 → 子类实例构造函数;
子类构造函数默认调用父类的无参构造函数,如需调用带参构造,用base(参数):
csharp

	public class Animal
	{
	public Animal(string type)
	{
	Console.WriteLine($"Animal类型:{type}");
	}
	}
	
	public class Dog : Animal
	{
	// 调用父类带参构造函数
	public Dog() : base("哺乳动物") 
	{
	Console.WriteLine("Dog构造函数");
	}
	}
	
	// 使用 → 输出:Animal类型:哺乳动物 → Dog构造函数
	Dog dog = new Dog();

3.2 析构函数执行顺序
子类析构函数 → 父类析构函数(与构造函数相反)。
3.3 推荐:用IDisposable释放资源
因析构函数执行时机不确定,实际开发中优先用IDisposable接口手动释放资源,配合using语句自动调用Dispose方法。
实例:
csharp

	// 实现IDisposable接口
	public class FileHandler : IDisposable
	{
	private FileStream _stream;
	private bool _disposed = false; // 标记是否已释放
	
	public FileHandler(string filePath)
	{
	_stream = new FileStream(filePath, FileMode.Open);
	}
	
	// 手动释放资源的方法
	public void Dispose()
	{
	Dispose(true);
	GC.SuppressFinalize(this); // 告诉GC无需再调用析构函数
	}
	
	// 受保护方法:处理托管/非托管资源
	protected virtual void Dispose(bool disposing)
	{
	if (!_disposed)
	{
	if (disposing)
	{
	// 释放托管资源(如_stream)
	_stream?.Close();
	}
	// 释放非托管资源(如Win32句柄)
	_disposed = true;
	}
	}
	
	// 析构函数:仅在未手动Dispose时调用
	~FileHandler()
	{
	Dispose(false);
	}
	}
	
	// 使用using语句 → 自动调用Dispose
	using (FileHandler fh = new FileHandler("test.txt"))
	{
	// 处理文件逻辑
	}
	// 离开using块时自动释放资源

总结
构造函数:初始化对象,分默认、自定义、静态三种,this解决参数与字段重名;
析构函数:释放非托管资源,执行时机不确定,不推荐依赖;
最佳实践:用IDisposable+using手动释放资源,确保及时、可靠。

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49360.html


相关教程