前言

最近看到小伙伴在.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. ORA-00020: maximum number of processes (40) exceeded模拟会话连接数满

    问题描述:在正式生产环境中,有的库建的process和session连接数目设置的较小,导致后期满了无法连接.因为正式库无法进行停库修改,只能释放连接,做个测试模拟 1. 修改现有最大会话与进程连接数 ...

  2. jdk的动态代理和静态代理你还写不出来嘛???

    一.什么叫jdk的代理? 用另外一个对象去代理实际对象的操作 分为动态代理和静态代理二.先说说静态代理 从字面意思来看就是不会改变的,只可以代理某个固定对象的. 静态代理就是通过实现和目标对象实现的同 ...

  3. 预估ceph的迁移数据量

    引言 我们在进行 ceph 的 osd 的增加和减少的维护的时候,会碰到迁移数据,但是我们平时会怎么去回答关于迁移数据量的问题,一般来说,都是说很多,或者说根据环境来看,有没有精确的一个说法,到底要迁 ...

  4. 编译一个支持多线程的php安装包

    前言 因为项目上的需要,需要用到php,一般来说,用默认的版本和配置就可以满足大多数的场景,因为需要加入多线程,所以需要自己编译一个包 一般来说,发行的包的版本的配置选项和代码都是最稳定的,所以在大多 ...

  5. CSS属性(边框)

    1.边框 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="U ...

  6. ACCESS渗透测试

    access-getshell 直接写shell # 创建临时表 create table test(a varchar(255)); # 插入一句话木马 insert into test(a) va ...

  7. [原题复现][极客大挑战 2019]BuyFlag

    简介  原题复现:[极客大挑战 2019]BuyFlag  考察知识点:php函数特性(is_numeric().strcmp函数())  线上平台:https://buuoj.cn(北京联合大学公开 ...

  8. 常见web漏洞修复方法

    方法如下: 漏洞修复.(输入过滤,输出转义) 1.在连接数据库时,在接收参数后进行转义,$id = mysql_real_escape_string($id); 2.在网页源码中在接收参数后可用htm ...

  9. leetcode 33和 leetcode81 II

    //接上上一篇博客,继续这个题目,现在数组中会有重复元素,情况将会变得十分复杂,比如说1,1,1,1,1   或者1,1,3,1再来 3,3,3,1,1,1,3,这些都是可以的,都是符合题目要求的,如 ...

  10. iOS问题:pch not found

    问题描述: clang: error: no such file or directory: '/Users/apple/Desktop/迅点App_Mark/FaceHelp/FaceHelp-Pr ...