前言

最近看到小伙伴在.NET Core中用到了析构函数,不禁打一疑问,大部分情况下,即使在.NET Framework中都不会怎么用到析构函数,我想在.NET Core中是否还依然有效呢?随着时间推移,迭代版本更新,有些当初我们脑海里认定的东西可能在当前并不再适用,这也就需要我们同步知识更新,如今我们所认为可能并不再是往昔我们所认为

.NET Core/.NET 5.0 析构函数

下面首先来看在.NET Framework中一个很标准的资源释放例子,这里我以4.7.2版本为例(其他版本一样)。创建基于当前应用程序域的指定程序集的指定实例

public class CurrentDomainSandbox : IDisposable
{
private AppDomain _domain = AppDomain.CreateDomain(
"CurrentDomainSandbox",
null,
new AppDomainSetup
{
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
}); ~CurrentDomainSandbox()
{
Dispose(false);
} public T CreateInstance<T>(params object[] args)
=> (T)CreateInstance(typeof(T), args); private object CreateInstance(Type type, params object[] args)
{
HandleDisposed(); return _domain.CreateInstanceAndUnwrap(
type.Assembly.FullName,
type.FullName,
ignoreCase: false,
bindingAttr: 0,
binder: null,
args: args,
culture: null,
activationAttributes: null);
} public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} protected virtual void Dispose(bool disposing)
{
if (disposing && (_domain != null))
{
AppDomain.Unload(_domain);
_domain = null;
}
} private void HandleDisposed()
{
if (_domain == null)
{
throw new ObjectDisposedException(null);
}
}
}

通过如上定义创建指定名称的应用程序域沙箱盒子,这样我们则可在此沙箱中创建对应程序集和实例,如此则可以其他域完全隔离且独立,然后在控制台进行如下调用

  var sanBox = new CurrentDomainSandbox();
var instance = sanBox.CreateInstance<Program>();

还未完毕,直接运行将抛出如下异常

若用于远程传输,我们直接将主类继承自MarshalByRefObject就好,否则将此类通过Serializable特性标记,至于二者区别不详细展开。通过上述比较标准的例子我们则可以创建和释放未被使用的对应实例,我们看到用到了析构函数,但是我们发现最终调用Dispose方法,并未做任何处理,其实不然,问题出在对析构函数概念的理解

析构函数:在应用程序终止之前,将调用尚未被垃圾回收的所有对象的析构函数。析构函数本质是终结器,如果对象已被释放,在合适时机将自动调用Finalize方法,除非我们手动,通过GC来抑制调用终结器(GC.SuppressFinalize),但不建议手动调用Finalize方法

通过资源释放标准例子,想必我们已经知道了析构函数的基本原理,接下来我们还是基于上述.NET Framework 4.7.2版本来演示析构函数

public class ExampleDestructor
{
public ExampleDestructor()
{
Console.WriteLine("初始化对象");
} public void InvokeExampleMethod()
{ } ~ExampleDestructor()
{
Console.WriteLine("终结对象");
}
}

既然析构函数是在应用程序终止前进行调用,那么我们在调用上述示例中方法时,如下调用:

var exampleDestructor = new ExampleDestructor();

exampleDestructor.InvokeExampleMethod();

在.NET Framework中如我们所期望,在应用程序卸载时,此时会调用析构函数并进行相关打印。接下来到.NET Core,此时将断点放在析构函数中,将不会再调用,打印如下:

好了,以上只是我个人猜测,接下来我们直接看官方文档进行论证,官网对于析构函数链接

析构函数规范

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/destructors

在.NET Framework应用程序中会尽一切合理努力在程序退出时调用析构函数进行清理(调用终结器方法),除非进行手动抑制,但在.NET Core并不能完全保证此行为。通过调用Collect来强制进行垃圾回收,但是在大多数情况下,应避免此调用,因为这可能会导致性能问题。为何出现如此差异呢?更详细分析请参看链接:

.NET Core析构函数理解分析

https://github.com/dotnet/runtime/issues/16028

根据此链接表述,可以这样理解:在.NET Core中不会在应用程序终止时运行终结器(针对可到达或不可到达的对象),根据建议,并不能保证所有可终结对象在关闭之前都将被终结。由于上述链接原因存在,所以在ECMA的C#5.0规范削弱了这一要求,因此.Net Core并不会违反此版本规范

总结

在应用程序关闭前,.NET Framework会尽一切合理努力调用析构函数即终结器进行资源清理,但在.NET Core中并不能保证此行为,所以在ECMA 语言规范中削弱了这一要求

基于上述,在.NET Core中使用析构函数并没有实质性意义

.NET Core/.NET 5.0 析构函数依然有效?的更多相关文章

  1. ASP.NET Core 1.1.0 Release Notes

    ASP.NET Core 1.1.0 Release Notes We are pleased to announce the release of ASP.NET Core 1.1.0! Antif ...

  2. ASP.NET Core实现OAuth2.0的ResourceOwnerPassword和ClientCredentials模式

    前言 开发授权服务框架一般使用OAuth2.0授权框架,而开发Webapi的授权更应该使用OAuth2.0授权标准,OAuth2.0授权框架文档说明参考:https://tools.ietf.org/ ...

  3. [转]Could not load file or assembly 'System.Core, Version=2.0.5.0 和autofac冲突的问题

    Could not load file or assembly 'System.Core, Version=2.0.5.0 和autofac冲突的问题 来源:http://www.cnblogs.co ...

  4. Asp.net Core 1.0.1升级到Asp.net Core 1.1.0 Preview版本发布到Windows Server2008 R2 IIS中的各种坑

    Asp.net Core 1.0.1升级到Asp.net Core 1.1.0后,程序无法运行了 解决方案:在project.json中加入runtime节点 "runtimes" ...

  5. Could not load file or assembly 'System.Core, Version=2.0.5.0 和autofac冲突的问题

    在部署到iis的时候会出现这个状况. 解决:下载安装这个补丁 http://support.microsoft.com/kb/2468871 http://www.microsoft.com/zh-c ...

  6. .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)

    .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一) 上一篇主 ...

  7. .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一)

    .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) Json是WEB交互常见的数据,.net core 处理方式是转为强类型,没有对应的强类型会被抛弃,有时 ...

  8. 使用Autofac部署IIS6.0时未能加载文件或程序集“System.Core, Version=2.0.5.0...“

    错误信息 .net4.0项目中使用autofac这个IOC容器,在部署在win2003+iis6时出现以下错误. “/”应用程序中的服务器错误. --------------------------- ...

  9. ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package

    目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我 ...

随机推荐

  1. 关于保存批量数据进入mysql

    提出的要求: 生成13位纯数字的卡号与8位纯数字的卡密,要求卡号与卡密都必须全表唯一,然后保存到mysql. 思路: 1.首先mysql中将这两个字段设置唯一索引,保证这两个字段的值在该表中是唯一存在 ...

  2. python爬虫构建代理ip池抓取数据库的示例代码

    爬虫的小伙伴,肯定经常遇到ip被封的情况,而现在网络上的代理ip免费的已经很难找了,那么现在就用python的requests库从爬取代理ip,创建一个ip代理池,以备使用. 本代码包括ip的爬取,检 ...

  3. HTML5 实现的一个俄罗斯方块实例代码

    /*实现的功能:方块旋转(W键).自动下落.移动(ASD).消行.快速下落(空格键).下落阴影.游戏结束.*/ <!DOCTYPE html>   <html>    < ...

  4. C# Span 源码解读和应用实践

    一:背景 1. 讲故事 这两天工作上太忙没有及时持续的文章产出,和大家说声抱歉,前几天群里一个朋友在问什么时候可以产出 Span 的下一篇,哈哈,这就来啦!读过上一篇的朋友应该都知道 Span 统一了 ...

  5. AHB SRAM控制器设计

  6. 查询SQL Server数据库使用的版本号信息

    如何查询当前连接服务器的数据库版本号,使用以下语句执行即可: select @@version

  7. arm-linux openssl移植

    从openssl官网下载openssl https://www.openssl.org/source/ 1.解压到linux中 2. ./config no-asm shared --prefix=$ ...

  8. Map结合Function函数式接口的巧妙之处

    需求:在给定 List 集合中,需根据不同的算法规则,选取计算方式并返回结果: 例如:[1, 2, 3, 4, 5] List 集合中都是 Integer 类型数据,根据提供的算法规则,sum 求和, ...

  9. [C/C++] 结构体内存对齐:alignas alignof pack

    简述: alignas(x):指定结构体内某个成员的对齐字节数,指定的对齐字节数不能小于它原本的字节数,且为2^n; #pragma pack(x):指定结构体的对齐方式,只能缩小结构体的对齐数,且为 ...

  10. 这行代码告诉你!为什么你地下城与勇士(DNF)的装备强化老是失败?

    模拟地下城与勇士(DNF)的装备强化 tip1: DNF装备强化在+1-+3 不会失败: +4-+7,失败后物品原有强化等级降低1级: +8-+10,失败后掉3级: 10上11或以上就爆了. tip2 ...