前言

最近看到小伙伴在.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. svg究竟是什么?

    svg究竟是什么? 1 要点 要点1:svg与jpg/png等格式的用途完全不同,不可相提并论,没有可比性,不可互相替代. 要点2:日常生活中,我们用相机拍摄自然景象得到的照片和视频,能且只能用jpg ...

  2. UOJ Round总结

    #22. [UR #1]外星人 一开始随便搞出第一问答案,很显然的性质对$x$有变化的$a$一定是递减的,就拿一个桶直接记录可以达到的值 然后我开始想第二问,一开始想直接在这个桶上统计答案,然后发现不 ...

  3. 3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案

    根据之前解析的循环依赖的源码, 分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下, Spring在创建bean的过程中, 可能会读取到不完整的bean. 下面, ...

  4. Zabbix + Cloud Alert 实践分享

    前言 如果要问老牌开源监控工具泰斗,当zabbix莫属.之前已分享过 [Kubernetes+Promethues+Cloud Alert实践分享],本篇将继续分享 Zabbix + Cloud Al ...

  5. 基于FFmpeg的Dxva2硬解码及Direct3D显示(一)

    目录 前言 名词解释 代码实现逻辑 前言 关于视频软解码的资料网上比较多了,但是关于硬解可供参考的资料非常之有限,虽然总得来说软解和硬解的基本逻辑一样,但是实现细节上的差别还是比较多的.虽然目前功能已 ...

  6. Docker与Ceph的分与合

    前言 docker是一个管理工具,在操作系统之上提供了一个新的独立轻环境,好处是本地提供了一个基础镜像,然后基于镜像再运行环境,也可以把环境重新打包为镜像,管理起来类似于git,感觉非常的方便,并且能 ...

  7. Mysql_笔记2018.1.29

    1.主要数据库 Oracle MySQL Sqlsever 微软 MongoDB (非关系型数据库) 2.MySql 专业词语 1.数据库:一些关联表的集合 2.数据表:表示数据的矩阵 3.列:同ex ...

  8. [LeetCode题解]141. 环形链表 | 快慢指针

    题目描述 给定一个链表,判断链表中是否有环. 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的 ...

  9. Gulp自动化构建的基本使用

    Study Notes 本博主会持续更新各种前端的技术,如果各位道友喜欢,可以关注.收藏.点赞下本博主的文章. Gulp 用自动化构建工具增强你的工作流程! gulp 将开发流程中让人痛苦或耗时的任务 ...

  10. mybatis-plus使用p6spy 插件进行sql性能分析

    1.依赖 <dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId& ...