.NET Core/.NET 5.0 析构函数依然有效?
前言
最近看到小伙伴在.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 析构函数依然有效?的更多相关文章
- 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 ...
- ASP.NET Core实现OAuth2.0的ResourceOwnerPassword和ClientCredentials模式
前言 开发授权服务框架一般使用OAuth2.0授权框架,而开发Webapi的授权更应该使用OAuth2.0授权标准,OAuth2.0授权框架文档说明参考:https://tools.ietf.org/ ...
- [转]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 ...
- 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" ...
- 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 ...
- .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)
.net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一) 上一篇主 ...
- .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一)
.net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) Json是WEB交互常见的数据,.net core 处理方式是转为强类型,没有对应的强类型会被抛弃,有时 ...
- 使用Autofac部署IIS6.0时未能加载文件或程序集“System.Core, Version=2.0.5.0...“
错误信息 .net4.0项目中使用autofac这个IOC容器,在部署在win2003+iis6时出现以下错误. “/”应用程序中的服务器错误. --------------------------- ...
- 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想试试,我 ...
随机推荐
- Luogu P2024 [NOI2001]食物链
并查集 首先先要读懂题目,a是b的食物的话,b的天敌是a,b的食物是a的天敌 比如,人吃鸡,鸡吃草,那么草吃人..... 所以建3个并查集,+n时表示这是其食物,+2*n时表示这是其天敌 所以当x,y ...
- CV 履历 格式
CV 指的是 "Curriculum Vitae" Curriculum vitae 在拉丁语中的意思是"生命的故事" CV 经常被称为 "Resum ...
- NO.A.0001——FIO工具使用教程
一.FIO工具安装: 1.FIO地址: 官网地址:http://freecode.com/projects/fio/ 源码安装包:http://brick.kernel.dk/snaps/fio-2. ...
- 僵尸进程与SIGCHLD信号
什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该 ...
- Andrew Ng 机器学习公开课 - 线性回归
我的机器学习系列从现在开始将会结合Andrew Ng老师与sklearn的api是实际应用相结合来写了. 吴恩达(1976-,英文名:Andrew Ng),华裔美国人,是斯坦福大学计算机科学系和电子工 ...
- 网络拓扑实例之VRRP负载分担(四)
组网图形 VRRP负载分担简介 负载分担方式是指多台设备同时承担业务,因此负载分担方式需要两个或者两个以上的虚拟路由器,每个虚拟路由器都包括一个Master路由器和若干个Backup路由器,各虚拟路 ...
- Collectiont和Collections的区别
Collectiont 和 Collections 的区别 Collection: 是Java提供的集合接口 存储一组不唯一,无序的对象 有两个子接口 List 和 Set Collections: ...
- ubuntu16.04搭建vulhub环境
简介 Vulhub官方中文教程https://github.com/vulhub/vulhub/blob/master/README.zh-cn.md 环境:ubuntu16.04.5 python3 ...
- 凭借着这份面经,我拿下了字节,美团的offer!
最近经常有粉丝私信问我问了一些诸如秋招该怎么复习的问题,我就想顺便把回答整理发一发.我也是把之前面试的一些经历经验和身边的人面试的经验总结了一下放在下面. 前期准备规划: 如果秋招的话一般过年回来就可 ...
- 如何基于App SDK快速地开发一个IoT App?
一.背景及大纲介绍 在如今物联网DCM(Device.Connect.Manage)的大框架下,有一个应用层来分析和处理数据,是必备技能.但是,对于一个公司来说,因为研发能力或者研发时间的原因,可能很 ...