C#托管类型与非托管类型简析

C#托管类型与非托管类型

定义

托管对象指的是.net可以自动进行回收的资源,主要是指托管对象在堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,有.net运行库在合适的时间进行回收。当然,也可以使用GC.Collect手动回收。

非托管对象指.net不知道如何回收的资源。例如文件、窗口、网络连接、数据库连接、画刷、图标等。这类资源,垃圾回收器在清理的时候会调用Object.Finalize()方法。默认情况下,方法是空的,对于非托管对象在此方法中需要编写回收非托管对象的代码,以便垃圾回收器正确回收。(例如我们通常打开文件、图片等后需要进行Close()或者Dispose()去释放)。

如果某个类型是以下类型之一,则它是非托管类型 :

  • sbytebyteshortushortintuintlongulongnintnuintcharfloatdoubledecimalbool
  • 任何枚举类型
  • 任何指针类型
  • 成员都是某个非托管类型的一个元组
  • 任何仅包含非托管类型字段的用户定义的结构类型。

可使用 unmanaged 约束指定:类型参数为“非指针、不可为 null 的非托管类型”。

仅包含非托管类型的字段的构造结构类型也是非托管类型,如以下示例所示:

using System;

public struct Coords<T>
{
    public T X;
    public T Y;
}

public class UnmanagedTypes
{
    public static void Main()
    {
        DisplaySize<Coords<int>>();
        DisplaySize<Coords<double>>();
    }

    private unsafe static void DisplaySize<T>() where T : unmanaged
    {
        Console.WriteLine($"{typeof(T)} is unmanaged and its size is {sizeof(T)} bytes");
    }
}
// Output:
// Coords`1[System.Int32] is unmanaged and its size is 8 bytes
// Coords`1[System.Double] is unmanaged and its size is 16 bytes

非托管资源的释放

Microsoft为非托管资源的回收专门定义了一个接口:IDisposable,接口中只包含一个Dispose()方法。任何包含非托管资源的类,都应该继承此接口。

在一个包含非托管资源的类中,关于资源释放的标准做法是:

(1)继承IDisposable()接口;

(2)实现Dispose()方法,在其中释放托管资源和非托管资源,并将对象本身从垃圾回收器中移除(垃圾回收器不在回收此资源);

(3)实现类析构函数,在其中释放非托管资源。

但是这样之后,如果单纯依赖手动释放,仍然是不保险的,有时我们可能忘了手动释放资源,或者如果出现异常,仍可能导致析构函数不被执行,造成内存泄漏。

所以有两种比较保险的做法,一种是使用try - catch - finally语句,另一种是使用using。后者的底层实现正是基于前者,两者没有本质区别。可以说using是C#的一个语法糖。但是如果using语句中分配的变量的类型没有实现IDisposable接口,编译器将会抛出异常。

如下面两段代码:

SqlConnection myConnection = null;
using (myConnection = new SqlConnection(connectionString))
{
    myConnection.Open();
}

try
{
	myConnection = new SqlConnection(connectionString);
	myConnection.Open();
}
finally
{
	myConnection.Dispose();
}

本质上是一样的。

对于一些可能实现或未实现IDisposable接口的对象,或者无法确定是否应该用using语句包裹某个对象时,由于其不确定性我们可以使用as操作符进行安全的销毁

 object obj = Factory.CreateResource();
//如果不确定obj是否实现了IDisposable接口,下面是安全的销毁方式
using (obj as IDisposable)
{
	Console.WriteLine(obj.ToString());
}
  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值