.NET Standard 来日苦短去日长( 二 )

  • 往后的共享代码 , 使用 net5.0 。
  • .NET 5 如何解决 .NET Standard 存在的问题.NET Standard 使得创建适用于所有 .NET 平台的库变得更加容易 , 但是 .NET Standard 仍然存在三个问题:
    1. 它的版本更新很慢[2] , 这意味着你不能轻松地使用最新的特性 。
    2. 它需要一个解码环[3]来将版本映射到 .NET 实现 。
    3. 它公开了特定于平台的特性[4] , 这意味着你不能静态地验证代码是否真正可移植 。
    让我们看看 .NET 5 将如何解决这三个问题 。
    问题 1:.NET Standard 版本更新慢在设计 .NET Standard[5] 时 , .NET 平台还没有在实现层次上融合 , 这使得编写需要在不同环境下工作的代码变得困难 , 因为不同的工作代码使用的是不同的 .NET 实现 。
    .NET Standard 的目标是统一基础类库(BCL)的特性集 , 这样你就可以编写一个可以在任何地方运行的单一库 。 这为我们提供了很好的服务:前 1000 个软件包中有超过 77% 支持 .NET Standard 。 如果我们看看 NuGet.org 上所有在过去 6 个月里更新过的软件包 , 采用率是 58% 。
    .NET Standard 来日苦短去日长文章插图
    但是只标准化 API 就会产生额外的付出 , 它要求我们在添加新 API 时进行协调——这一直在发生 。 .NET 开源社区(包括.NET 团队)通过提供新的语言特性、可用性改进、新的交叉(cross-cutting)功能(如 Span)或支持新的数据格式或网络协议 , 不断对 BCL 进行创新 。
    而我们虽然可以以 NuGet 包的形式提供新的类型 , 但不能以这种方式在现有类型上提供新的 API 。 所以 , 从一般意义上讲 , BCL 的创新需要发布新版本的 .NET 标准 。
    在 .NET Standard 2.0 之前 , 这并不是一个真正的问题 , 因为我们只对现有的 API 进行标准化 。 但在 .NET Standard 2.1 中 , 我们对全新的 API 进行了标准化 , 这也是我们看到相当多摩擦的地方 。
    这种摩擦从何而来?
    .NET 标准是一个 API 集 , 所有的.NET 实现都必须支持 , 所以它有一个编辑方面[6]的问题 , 所有的 API 必须由 .NET Standard 审查委员会[7]审查 。 该委员会由 .NET 平台实现者以及 .NET 社区的代表组成 。 其目标是只对我们能够真正在所有当前和未来的 .NET 平台中实现的 API 进行标准化 。 这些审查是必要的 , 因为 .NET 协议栈有不同的实现 , 有不同的限制 。
    我们预测到了这种类型的摩擦 , 这就是为什么我们很早就说过 , .NET 标准将只对至少一个 .NET 实现中已经推出的 API 进行标准化 。 这乍一看似乎很合理 , 但随后你就会意识到 , .NET Standard 不可能频繁地更新 。 所以 , 如果一个功能错过了某个特定的版本 , 你可能要等上几年才能使用 , 甚至可能要等更久 , 直到这个版本的 .NET Standard 得到广泛支持 。
    我们觉得对于某些特性来说 , 机会损失太大 , 所以我们做了一些不自然的行为 , 将还没有推出的 API 标准化(比如 AsyncEnumerable) 。 对所有的功能都这样做实在是太昂贵了 , 这也是为什么有不少功能还是错过了 .NET Standard 2.1 这趟列车的原因(比如新的硬件特性) 。
    但如果有一个单一的代码库呢?如果这个代码库必须支持所有与 .NET 至今所实现功能有所不同的特性 , 比如同时支持及时编译(JIT)和超前编译(AOT)呢?
    与其在事后才进行这些审查 , 不如从一开始就将所有这些方面作为功能设计的一部分 。 在这样的世界里 , 标准化的 API 集从构造上来说 , 就是通用的 API 集 。 当一个功能实现后 , 因为代码库是共享的 , 所以大家就已经可以使用了 。
    问题 2:.NET Standard 需要解码环将 API 集与它的实现分离 , 不仅仅是减缓了 API 的可用性 , 这也意味着我们需要将 .NET Standard 版本映射到它们的实现上[3] 。 作为一个长期以来不得不向许多人解释这个表格的人 , 我已经意识到这个看似简单的想法是多么复杂 。 我们已经尽力让它变得更简单 , 但最终 , 这种复杂性是与生俱来的 , 因为 API 集和实现是独立发布的 。


    推荐阅读