游乐游手机版
首页/编程语言/文章详情

Unity C#非托管资源清理代码详解

时间:2026-07-27 19:29
在C 中,非托管资源如文件句柄、数据库连接需手动释放。Dispose模式通过IDisposable接口标准化清理流程,包含幂等性、层级调用、GC SuppressFinalize优化及有参 无参Dispose方法。终结器作为兜底方案,但性能开销大,仅用于非托管资源。

一、理解托管资源与非托管资源

在C#编程中,资源管理是开发者必须掌握的核心技能。C#中的对象主要分为两类:托管对象由.NET垃圾回收器(GC)自动管理,无需手动干预;而非托管对象则需要开发者显式释放,因为GC无法自动回收。常见的非托管资源包括文件句柄、窗口句柄、网络连接和数据库连接等。如果使用后不及时清理,就会导致内存泄漏,影响程序性能。

C#/Unity清理非托管资源的代码详解

二、区分托管对象与非托管对象

为了更清晰地理解这两类对象的区别,请参考以下对比表格:

对比维度托管对象非托管对象

常见类型

C#中通过 new 创建的对象、class、struct、string 等

IntPtr、Windows 句柄、unsafe 代码中的指针等

内存管理方式由 .NET 垃圾回收器(GC)自动管理,无需手动干预必须由开发者手动分配和释放
典型示例FileStream、SqlConnection、Person、List 等文件句柄、GDI 绘图对象、Marshal.AllocHGlobal 分配的内存等

三、Dispose 模式

3.1 Dispose 模式概述

为此,微软提供了一套标准方案——释放模式(Dispose Pattern),旨在规范非托管资源的释放流程,降低开发者的心智负担。该模式遵循以下两个核心准则:

1. 幂等性:Dispose 方法应支持多次调用,后续调用不会产生任何副作用。

2. 层级调用:如果一个类包含实现了 IDisposable 的成员,那么该类本身也应实现 IDisposable,并在其 Dispose 方法中调用这些成员的 Dispose 方法。

3.2 IDisposable 接口

该模式的核心接口是 IDisposable,它仅定义了一个无参方法 Dispose:

namespace System
{
    [ComVisible(true)]
    public interface IDisposable
    {
        void Dispose();
    }
}

3.3 无参 Dispose 方法

以下是其标准实现:

public void Dispose()
{
    // 释放非托管资源
    Dispose(true);
    // 抑制终结器,避免重复释放
    GC.SuppressFinalize(this);
}

3.4 GC.SuppressFinalize 的作用

SuppressFinalize 的主要作用是性能优化:它通知 GC 该对象已被手动释放,无需再执行终结流程,从而让 GC 可以提前回收该对象的内存。此方法会阻止终结器(析构函数)的执行。如果类中没有定义终结器,则调用 GC.SuppressFinalize 不会产生任何效果。

3.5 有参 Dispose 方法

实际执行清理任务的是以下重载方法。参数 disposing 为 true 表示由无参 Dispose() 方法主动调用,为 false 则表示由终结器调用:

protected virtual void Dispose(bool disposing)
{
    if (_disposed)
    {
        return;
    }

    if (disposing)
    {
        // 释放托管资源(托管对象)
        // ...
    }

    // 释放非托管资源
    // ...

    _disposed = true;
}

该方法之所以同时处理两种场景,是为了避免代码重复并确保安全性:

  • 确定性释放(disposing = true):当主动调用 Dispose() 时触发,此时托管和非托管资源都可以安全释放。
  • 非确定性释放(disposing = false):由 GC 在终结器中触发,此时托管资源可能已被回收,因此只应释放非托管资源。

3.6 使用实现 IDisposable 的对象

如果通过 new 创建的对象实现了 IDisposable(例如 StreamReader),则使用后必须调用其 Dispose 方法。常见做法有两种:

方法一:try-finally 结构

        StreamReader sr;
        try
        {
            sr = new StreamReader(filename);
            txt = sr.ReadToEnd();
        }
        finally
        {
            if (sr != null) sr.Dispose();
        }

方法二:using 语句

当控制离开 using 语句块时,会自动调用 Dispose 方法。实际上,using 是语法糖,编译后等价于上面的 try-finally 结构。

        using (StreamReader sr = new StreamReader(filename))
        {
            txt = sr.ReadToEnd();
        }

此外,还可以使用不带括号的 using 声明。在这种写法下,Dispose 会在当前方法结束时自动触发:

using StreamReader sr = new StreamReader(filename);
txt = sr.ReadToEnd();

四、终结器(Finalizer)

终结器(历史上称为析构函数)会在 GC 回收对象内存之前由 GC 调用,相当于一个兜底方案:当开发者忘记手动调用 Dispose 时,终结器可以防止内存泄漏。但它的代价是增加 GC 的性能开销,因此不推荐作为常规做法。

  • 终结器应仅用于非托管对象。
  • C# 编译器不允许直接重写 Finalize 方法,但可以通过在类中定义析构函数来提供终结器。
  • 避免编写空的终结器,因为空终结器只会无谓地消耗性能。

例如,以下 Car 类的终结器声明:

class Car
{
    ~Car()  // 终结器
    {
        // 清理语句...
    }
}

编译器会将终结器隐式转换为以下代码:

protected override void Finalize()
{
    try
    {
        // 清理语句...
    }
    finally
    {
        base.Finalize();
    }
}
来源:https://www.jb51.net/program/368118u82.htm
上一篇如何在Linux下控制Golang日志文件的权限 下一篇Java线程池ThreadPoolExecutor参数配置详解
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
35岁转行网络安全:从经验复用到实战落地的可行性评估
编程语言 · 2026-10-10

35岁转行网络安全:从经验复用到实战落地的可行性评估

35岁转行网络安全并非不可行,但核心在于将过往经验转化为安全领域的差异化优势。本文从岗位匹配度、技能学习顺序、实战验证闭环、求职策略及常见误区五个维度,提供一套可执行的转行评估框架与行动指南,帮助读者理性判断投入产出比,避开无效学习陷阱。

网络安全行业前景分析:技术演进与市场机遇
编程语言 · 2026-10-10

网络安全行业前景分析:技术演进与市场机遇

围绕2026年网络安全行业的发展变化,从市场需求、技术演进、细分赛道和企业落地四个层面展开,帮助读者理解行业增长逻辑、识别重点技术方向,并建立评估市场机遇与风险的基本框架。 OWASP China +2 IDC +2

2026网络安全求职全景:从岗位拆解到实战作品集构建
编程语言 · 2026-10-10

2026网络安全求职全景:从岗位拆解到实战作品集构建

本文基于2026年网络安全行业招聘趋势,深入剖析安全运维、攻防渗透、云安全等核心岗位的技术栈差异与能力侧重。文章不仅梳理了从基础网络知识到高级攻防演练的学习路径,更提供了“以终为始”的求职策略:通过拆解JD反向验证技能缺口,并指导如何将CTF经历、HomeLab实验转化为具有说服力的项目作品集,帮助

2024安全攻防实战:从勒索软件到AI治理的破局与重构
编程语言 · 2026-10-10

2024安全攻防实战:从勒索软件到AI治理的破局与重构

2024年的网络安全已从单纯的技术对抗演变为业务连续性的生死博弈。本文基于ENISA、微软及世界经济论坛的最新报告,深入剖析勒索软件的“双重勒索”演变、身份凭证成为首要攻击面的现状,以及生成式AI带来的攻防不对称性。文章进一步拆解企业如何从被动防御转向“发现-保护-检测-响应-恢复”的闭环体系,重点

网站编程AI工具测评:提升开发效率的辅助软件推荐
编程语言 · 2026-10-10

网站编程AI工具测评:提升开发效率的辅助软件推荐

围绕网站开发中的实际需求,对AI编程辅助工具进行分类、操作体验与效果验证,帮助读者快速判断哪些工具真正能提升开发效率,并避开代码质量、隐私、安全与过度依赖等常见问题。