前言

最近看到小伙伴在.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. 分享JDK解压版(ZIP)

    目录 由于安装版本的jdk不太方便,所以我分享一下如何去获取解压版的jdk,jdk配置的话看这个文章 一.先下载exe版本的jdk安装程序: 二.使用7-ZIP解压工具 2.1 JDK8的解压目录 2 ...

  2. python-找不到tk包

    找不到-tk包 直接sudo apt-get install python3-tk 或者sudo apt-get install python-tk 百度上的方法不可信,还是直接这样一句命令来的实在

  3. 炸了!一口气问了我18个JVM问题!

    前言 GC 对于Java 来说重要性不言而喻,不论是平日里对 JVM 的调优还是面试中的无情轰炸. 这篇文章我会以一问一答的方式来展开有关 GC 的内容. 不过在此之前强烈建议先看这篇文章深度揭秘垃圾 ...

  4. 纯CSS实现3D正方体动画效果

    前言 纯CSS实现3D正方体动画效果,此方法是通过transform的旋转(rotate)和位移(translate)实现的,具体效果是鼠标滑过时正方体的一个面会产生位移 效果图 ​

  5. Java 中数组转换为 List

    目录 1 - int 型数组转换为 List 2 - List 转换为 int 型数组 3 - String 型数组转换为 List 4 - List 转换为 String 型数组 版权声明 开发中经 ...

  6. 都知道的copy_from_user

    Q:一直知道内核和用户态的数据交互前都需要 校验地址的合法性,一般都用copy_from/to_user完成数据拷贝,那么为什么要这样呢?? A:看了一些blog以及Stack Overflow 主要 ...

  7. symbol lookup error /usr/lib/x86_64-linux-gnu/libstdc++.so.6错误的解决办法

    当出现 $ apt-get: symbol lookup error: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: undefined symbol: _ZNS ...

  8. MyBatis 使用手册

    MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作.MyBatis 可以通过简单的 XM ...

  9. html图片拖放

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...

  10. 看阿里P7讲MyBatis:从MyBatis的理解以及配置和实现全帮你搞懂

    前言 MyBatis 是一款优秀的持久层框架,一个半 ORM(对象关系映射)框架,它支持定制化 SQL.存储过程以及高级映`射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结 ...