c#中的托管、非托管、垃圾回收、using

托管

什么是托管代码? | Microsoft Docs

托管代码是指运行时交给CLR(Common Language Runtime)管理的代码。

CLR负责提取托管代码,将其编译成机器代码,然后执行它。

除此之外,CLR还提供多个重要服务,例如自动内存管理、安全边界、类型安全,等等。

非托管

非托管类型 - C# 参考 | Microsoft Docs

清理未托管资源 | Microsoft Docs

非托管资源的对象,需要程序员在使用完后显示释放。

常见用的非托管资源类型是包装操作系统资源的对象,如文件、窗口、网络连接或数据库连接。

垃圾回收器可以跟踪封装非托管资源的对象的生存期,但无法清理这些非托管资源。

如果你的类型使用非托管资源,则应执行以下操作:

  • 实现清理模式。这要求资源对象继承IDisposable.Dispose接口类型。当不再需要此对象(或资源)时,类型使用者可以调用Dispose方法。(Dispose方法可立即释放非托管资源)
  • 在类型使用者忘记调用Dispose时,请提供一种方法来释放非托管资源。有两种方法可以实现此目的:

方法1:使用安全句柄包装非托管资源。(推荐使用安全句柄)

       安全句柄派生自System.Runtime.InteropServices.SafeHandle 抽象类,并包含可靠的 Finalize 方法。 在使用安全句柄时,只需实现 IDisposable 接口并在 Dispose 实现中调用安全句柄的 IDisposable.Dispose 方法。 如果未调用安全句柄的 Dispose 方法,则垃圾回收器将自动调用安全句柄的终结器。

方法2:重写Object.Finalize方法。

注意:

        类型使用者可直接调用 IDisposable.Dispose 实现以释放非托管资源使用的内存。 在正确实现 Dispose 方法时,安全句柄的 Finalize 方法或 Object.Finalize 方法的重写会在未调用 Dispose 方法的情况下阻止清理资源。

垃圾回收

垃圾回收器GC被CLR初始化后,会分配一段内存用于存储和管理对象。此内存称为托管堆(与操作系统中的本机堆相对)

每个托管进程都有一个托管堆。

using

1、using指令

(1)从单个命名空间导入所以类型

using System.Text;

(2)为命名空间创建别名

using Project = PC.MyCompany.Project;

(3)与global搭配使用、与static搭配使用

// global using :将应用于编译中的所有文件(通常是一个项目) 
global using static System.Math;
using static System.Console;
using static System.Math;
class Program
{
    static void Main()
    {
        WriteLine(Sqrt(3*3 + 4*4));
    }
}

2、using语句

using语句可确保调用Dispose方法,或DisposeAsync方法。即使using块中发生异常也是如此。

string manyLines=@"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";

using (var reader = new StringReader(manyLines))
{
    string? item;
    do {
        item = reader.ReadLine();
        Console.WriteLine(item);
    } while(item != null);
}

上面的代码在编译时将扩展为以下代码:

string manyLines=@"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";

{
    var reader = new StringReader(manyLines);
    try {
        string? item;
        do {
            item = reader.ReadLine();
            Console.WriteLine(item);
        } while(item != null);
    } finally
    {
        reader?.Dispose();
    }
}


补充面试题:

问题:using可以回收声明定义的对象,可是.net中已经有垃圾回收器了,那为什么还要用using?

答案:.net中的垃圾回收器是用来自动回收托管对象的,不能回收非托管对象。

            非托管对象资源是与需要手动显示(调用非托管对象的Dispose方法)。

            using语句在非托管对象被使用完后,会自动去调用这个非托管对象的Dispose方法,这样就能确保非托管资源被正确释放掉了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值