托管
托管代码是指运行时交给CLR(Common Language Runtime)管理的代码。
CLR负责提取托管代码,将其编译成机器代码,然后执行它。
除此之外,CLR还提供多个重要服务,例如自动内存管理、安全边界、类型安全,等等。
非托管
非托管类型 - C# 参考 | 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方法,这样就能确保非托管资源被正确释放掉了。