.NET Standard是一套协议规范,不像.NET Framework,后者是一个完整的技术框架,而前者只是定义了一套规范,遵守这套规范的.NET Standard类库可以被不同.NET框架引用,比如.NET Core项目和.NET Framework项目都可以引用这个类库。

Standard这个单词就是标准、规范的意思,.NET Standard旨在建立一套标准,解决不同.NET框架之间的兼容性问题。

关于.NET Standard的概念以及版本支持的知识,请大家参考MSDN的介绍:https://docs.microsoft.com/zh-cn/dotnet/standard/net-standard

下面我们用.NET Core和.NET Framework框架为例介绍.NET Standard为什么能解决不同.NET框架之间的兼容性问题

在.NET Core项目中,我们所使用的类所在的程序集从表面上看和.NET Framework是一模一样的,那既然他们使用的程序集是完全一样的,为什么前者可以跨平台,而后者不可以呢?关于这个问题,请看我的另一篇文章:.NET Framework类型转移。

说到这里,我想到一个问题,为什么微软要使用类型转移这个技术呢?直接使用对应框架的对应程序集不就可以了吗。我是这样想的:因为.NET Framework框架出来的时间比.NET Core框架出来的时间早很多,微软为了让大家能够适应.NET Core,所以每个类所在的程序集都没有变化,但实际上,微软使用类型转移技术在背后把原程序集都重定向到了.NET Core的程序集上。这个操作是透明的,所以我们感觉不到。

下面我们用代码说话吧

我们新建一个.NET Standard的类库,版本为2.0。然后新建一个Utils的类,代码如下:

public class Utils{public static void PrintAssemblyNames(){Console.WriteLine(typeof(Dictionary<,>).Assembly.FullName);Console.WriteLine(typeof(SortedDictionary<,>).Assembly.FullName);}}

我们输出了这两个类型所在的程序集。

然后我们新建两个项目,一个.NET Framework 4.7.2,一个.NET Core 3.1,这两个项目都是控制台程序,代码如下:

static void Main(string[] args){Console.WriteLine(".NET Framework 4.7.2");Utils.PrintAssemblyNames();Console.ReadKey();}
static void Main(string[] args){Console.WriteLine(".NET Core 3.1");Utils.PrintAssemblyNames();Console.ReadKey();}

这两个项目都只做了一件事,在当前项目中输出上面两个类所在的程序集的信息。下面我们看一下输出结果:

可以看到,在不同的项目中输出的程序集是不一样的。下面我们就来了解一下为什么不一样。

首先我们看Dictionary类,在.NET Standard项目中,转到Dictionary的定义,在页面顶部可以看到它所在的程序集是netstandard。因为.NET Framework的版本是4.7.2,运行时是CLR4.0,所以我们找到CLR4.0下的netstandard.dll,这个dll在我电脑上的路径是:C:\Windows\Microsoft.NET\Framework\v4.0.30319\netstandard.dll,找到后使用ildasm.exe打开这个dll,双击MANIFEST,点击查找System.Collections.Generic.Dictionary,可以看到如下代码:

.class extern forwarder System.Collections.Generic.Dictionary`2
{.assembly extern mscorlib
}

这个代码的意思是System.Collections.Generic.Dictionary类被定义在程序集mscorlib中,所以在.NET Framework4.7.2项目下,Dictionary类所在的程序集是mscorlib。

使用同样的方法,查找到netstandard在.NET Core下面的路径:C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.4\netstandard.dll,同样反编译这个dll,可以看到如下代码:

.class extern forwarder System.Collections.Generic.Dictionary`2
{.assembly extern System.Collections
}
.class extern forwarder System.Collections.Generic.SortedDictionary`2
{.assembly extern System.Collections
}

这两个类型都被重定向到System.Collections中,但是从输出结果中可以看到Dictionary的结果集是System.Private.CoreLib,这是为什么呢?因为它被二次转移了,为了验证这个问题,我们在同样的目录下找到System.Collections.dll,使用反编译工具打开这个dll,可以看到如下代码:

.class extern forwarder System.Collections.Generic.Dictionary`2
{.assembly extern System.Private.CoreLib
}

所以在.NET Core的项目中Dictionary类型所在的程序集是System.Private.CoreLib。

其实这里有个容易被大家忽视的细节,从这个细节也可以看出这两个类所在的程序集。我们在.NET Core和.NET Framework项目中也定义一个Dictionary类,然后转到它的定义,可以看出在.NET Core项目中,它所在的程序集是System.Collections,但是因为有二次转移,所以最终所在程序集是System.Private.CoreLib;在.NET Framework项目中,它所在的程序集就是mscorlib;但是在.NET Standard项目中,它所在的程序集是netstandard。

.NET Standard类库之所以能够兼容其他的.NET框架,就是因为这个netstandard.dll。在这个项目类库中所有类型的所在程序集都是netstandard.dll,然后所有的.NET框架也都实现了这个程序集中的类型,通过类型转移(也称垫片程序集),最终调用的程序集是引用这个类库的项目的运行时程序集,这就是.NET Standard能够兼容其他.NET框架的原因。

.NET Standard详解相关推荐

  1. PHP autoload机制详解

    PHP autoload机制详解 转载自 jeakccc PHP autoload机制详解 (1) autoload机制概述 在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个 ...

  2. head和tail命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/amosli/p/3496027.html 当要查看上千行的大文件时,我们可不会用cat命令把整个文件内容给打印出来,相 ...

  3. Python字符编码详解

    Python字符编码详解 转自http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html Python字符编码详解 本文简单介绍了各种常用的 ...

  4. php各种编码集详解和在什么情况下进行使用 [php 字符集 显示]

    http://blog.cnsunrun.com/member/blog/blog_info/30/84 ----------------------------------------------- ...

  5. 全球著名音乐抓轨软件EAC 设置详解

    EAC的作者Andre Wiethoff是德国多特蒙德大学计算机专业的一名学生,经常抓取和监听各种WAV文件,所以使用了许多抓音轨的软件,但令他不满意的是,这些软件只有 时基误差的校正,而CDROM在 ...

  6. Python中的__name__和__main__含义详解

    背景 在写Python代码和看Python代码时,我们常常可以看到这样的代码: ? 1 2 3 4 5 def main():     ...... if __name__ == "__ma ...

  7. Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析

    转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...

  8. Stuts的Web.xml 详解

    1 定义头和根元素 部署描述符文件就像所有XML文件一样,必须以一个XML头开始.这个头声明可以使用的XML版本并给出文件的字符编码. DOCYTPE声明必须立即出现在此头之后.这个声明告诉服务器适用 ...

  9. nagios 3.2安装详解(一)

    Nagios 安装详解 对于运维人员来说,获悉服务器状况的信息非常重要,针对监控服务,比较好的有cacti和nagios,cacti使用更简单一些,cacti主要是用来采集信息,CPU.MEM.流量等 ...

  10. Linux系统详解 系统的启动、登录、注销与开关机

    Linux系统详解 第六篇:系统的启动.登录.注销与开关机 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://johncai.blo ...

最新文章

  1. ajax报403错,django使用ajax post数据出现403错误如何解决
  2. 如何让您的php也支持pthreads多线程
  3. Linux系统篇-文件系统虚拟文件系统
  4. content type 介绍
  5. bootstrap中表格大小设置_bootstrap 设置table - td宽度问题
  6. 利用airTest的图像实别技术测试Web应用
  7. 普通用户竟这样执行xp_cmdshell存储过程!
  8. pycharm导入本地文件,程序运行正常,但导入模块时出现红色波浪线
  9. 网吧版XP系统制作与优化终极版(转)
  10. 计算机二级考试办公软件高级应用题型,计算机二级考试题型
  11. 数据统计分析(SPSS)【8】
  12. 属牛的女孩取名:优美文雅、声声入耳的女孩名字
  13. 锐捷笔试题java_2018秋招锐捷笔试试题
  14. Axure旋转与移动效果
  15. 适合笔记本计算机玩的游戏,十款,笔记本电脑可以畅玩的单机游戏
  16. Java遍历jar包所有类-后续
  17. 4kw机柜无通道封闭CFD模拟分析及优化(下篇) -孙长青
  18. 修改 SSH 端口号
  19. UI设计师有哪些就业方向选择?
  20. 永恒之蓝漏洞复现(ms17-010)

热门文章

  1. 如何看出一个程序员的技术能力和水平?
  2. linux防挂马软件,Linux利用Python脚本检测网站挂马程序
  3. BI 工具常用图表用法
  4. 字谜游戏(b)C语言
  5. Arcgis修改栅格数据像素值
  6. vs2017配置 opengl + glfw + glad 环境
  7. BuBu笔记——MyBatis进阶-多表查询(秃头BUBu的超详细备注,一定要看哦)
  8. Scratch编程与数学之求累加和!
  9. 深度学习工程实践 5. libtorch+opencv使用复杂的训练分割模型(脸部,头发实现分割)
  10. 【历史上的今天】11 月 8 日:为开源献身的互联网之子;卷积神经网络 LeNet-5 问世;特斯拉发明遥控器