C类相关特性深入解析
立即解锁
发布时间: 2025-08-21 00:06:04 阅读量: 2 订阅数: 8 


C#编程基础与实战技巧
### C# 类相关特性深入解析
#### 1. 析构函数(Destructors)
析构函数用于在类的实例不再被引用后,执行清理或释放非托管资源的操作。以下是关于析构函数的重要知识点:
- 每个类只能有一个析构函数。
- 析构函数不能有参数。
- 析构函数不能有访问修饰符。
- 析构函数的名称与类名相同,但前面有一个波浪号(~)。
- 析构函数只作用于类的实例,因此没有静态析构函数。
- 不能在代码中显式调用析构函数,它会在垃圾回收过程中被调用,当垃圾回收器分析代码并确定对象不再被引用时触发。
示例代码如下:
```csharp
Class1
{
~Class1() // 析构函数
{
CleanupCode
}
...
}
```
使用析构函数的重要准则:
- 如果不需要,不要实现析构函数,因为它们可能会带来性能开销。
- 析构函数应该只释放对象拥有的外部资源。
- 析构函数不应访问其他对象,因为不能假设这些对象尚未被销毁。
在 C# 3.0 版本发布之前,析构函数有时被称为终结器,在文献和 .NET API 方法名中可能仍会遇到这个术语。
#### 2. 调用析构函数
与 C++ 析构函数不同,C# 析构函数在实例超出作用域时不会立即被调用,而且无法知道析构函数何时会被调用,也不能显式调用。如果代码需要析构函数,必须为系统提供它,系统会在对象从托管堆中移除之前的某个时间调用。
如果代码包含需要及时释放的非托管资源,不应将此任务留给析构函数,因为不能保证析构函数会很快运行。相反,应该采用标准模式,让类实现 `IDisposable` 接口。这包括将这些资源的清理代码封装在一个无参数的 `void` 方法中,该方法应命名为 `Dispose`。
`Dispose` 方法的使用准则:
- 实现 `Dispose` 方法的代码,使其可以安全地被多次调用。如果已经调用过,后续调用不应引发异常或执行额外的工作。
- 编写 `Dispose` 方法和析构函数,使得如果代码因某种原因未能调用 `Dispose`,析构函数将调用它并释放资源。
- 由于 `Dispose` 方法负责清理,它应该调用 `GC.SuppressFinalize` 方法,告诉 CLR 不要调用该对象的析构函数,因为清理工作已经完成。
安全处置过程的代码示例:
```csharp
class MyClass
{
bool disposed = false; // 标记处置状态
////////////////////////////////////////////////////////
public void Dispose() // 公共 Dispose 方法
{
if (disposed == false) // 检查标记
{
// 调用需要的托管资源的 Dispose 方法
...
// 释放对象持有的任何非托管资源
...
}
disposed = true; // 设置标记以显示已处置
GC.SuppressFinalize(this); // 告诉 GC 不要调用 Finalize
}
////////////////////////////////////////////////////////
~MyClass() // 析构函数
{
if (disposed == false) // 检查标记
{
// 释放任何非托管资源
...
}
}
...
}
```
析构函数中的过程与 `Dispose` 方法类似,但更简短。只需检查对象是否已经清理,如果没有,则释放非托管资源。注意,在这种情况下,不要调用任何托管资源的 `Dispose` 方法,因为垃圾回收器可能已经删除了这些对象。
#### 3. 标准 `Dispose` 模式
析构函数代码本质上是 `Dispose` 代码的子集。标准模式将这两个方法的大部分公共代码提取到另一个名为 `Dispose` 的方法中,这里称为分解后的 `Dispose` 方法。它接受一个布尔参数,用于指示该方法是从公共 `Dispose` 方法(`true`)还是从析构函数(`false`)调用的。
示例代码如下:
```csharp
class MyClass : IDisposable
{
bool disposed = false; // 处置状态
public void Dispose()
{
Dispose( true ); // 公共 Dispose
GC.SuppressFinalize(this);
}
~MyClass()
{ // 析构函数
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposed == false)
{
if (disposing == true)
{
// 处置托管资源
...
}
// 处置非托管资源
...
}
disposed = true;
}
}
```
#### 4. 比较构造函数和析构函数
| 类型 | 调用时机和频率 |
| ---- | ---- |
| 实例构造函数 | 在创建类的每个新实例时调用一次。 |
| 实例析构函数 | 在程序流无法再访问类的每个实例后的某个时间调用。 |
| 静态构造函数 | 仅调用一次,在首次访问类的任何静态成员之前或在创建类的任何实例之前调用,以先发生者为准。 |
| 静态析构函数 | 不存在,析构函数仅作用于实例。 |
#### 5. `readonly` 修饰符
可以使用 `readonly` 修饰符声明字段,其效果类似于将字段声明为 `const`,即一旦设置了值,就不能更改。
- `const` 字段只能在字段的声明语句中初始化,而 `readonly` 字段可以在以下任何位置设置其值:
- 字段声明语句,与 `const` 类似。
- 类的任何构造函数。
0
0
复制全文
相关推荐










