.NET Standard, .NET Core, PCL

48

.NET Standard 是一个令人困惑的概念。标准的 .NET 库格式听起来很好,但它确切是什么并不清楚。现在在 Visual Studio 中有 .NET Core 和 .NET Standard 类库项目模板,以及旧的 PCL 项目。如果您进入项目设置,您还可以将现有的 PCL 库转换为 .NET Standard。不清楚 .NET Standard 是一个库还是一个 DLL 格式。

我要问的基本问题是,我们应该针对哪种类型的库? 我主要是为 Xamarin 项目做这个,但如果我们能与其他平台共享这些库,特别是 .NET Core 和 UWP,那就太好了。让人困惑的是,微软同时推出了两种看似相同的类库类型:.NET Core 和 .NET Standard。

定义

NET Core - 一个符合 .NET Standard API 定义的基于 .NET 的运行时环境。

PCL - 一个由多个运行时环境支持的基于 .NET 的库格式,包括 .NET、Mono、UWP 等。

.NET Standard(定义1) - 一组用于 .NET 基础运行时环境的标准 API 定义。

.NET Standard(定义2) - 一个由多个运行时环境支持的基于 .NET 的库格式,包括 .NET、Mono、UWP 等,是 PCL 格式的延续。在 Visual Studio 中,可以通过进入项目属性并编辑目标框架来将 PCL 库转换为 .NET Standard 库。


1
阅读https://learn.microsoft.com/dotnet/articles/standard/library。 - Sir Rufo
2
忘记PCL吧,因为它很快就要消失了。.NET Standard是一个标准,所以在你的情况下,应该创建一个针对特定.NET Standard的.NET Core库,从1.0开始。试着玩一下,这些概念会自然而然地解释清楚。 - Lex Li
最近我尝试了这个。但是,我发现 Xamarin 项目不接受 .NET Standard 的 dll 作为引用。 - Christian Findlay
本文解释了为什么.NET Standard仍然很重要:https://christianfindlay.com/2020/12/21/net-standard/ - Christian Findlay
4个回答

27

关于这个问题的文件确实令人困惑,但大致可以理解为:

  • PCL:针对一组平台的库(具有这些平台的API的“最小公共分母”)。因此,在编写PCL时,您要表示我要针对A、B、C平台。

  • .NET标准:一组“标准”API而不是一个平台。因此,基本上您不需要关心平台,只需关注标准(版本1.3、1.6等),您的代码将在支持它的所有平台上运行。

  • .NET Core在这里不应混淆,它是.NET框架的“另一个版本”。.NET标准将跨运行时工作(.NET框架、.NET Core、Mono)。

所以我想.NET标准是正确的选择 :)


虽然这听起来很有道理,但它与事实相矛盾,即您实际上可以将PCL库项目转换为.NET Standard。在那时,您必须选择.NET Standard版本。真正让我困惑的是,我实际上正在编译成什么格式?我甚至不知道。 - Christian Findlay

10

以下内容来自 Samuel Englard (https://github.com/dotnet/corefx/issues/973#issuecomment-249582799):

.NET DLLs是按照ECMA-335格式(通常称为公共语言基础结构)进行格式化的。这种格式在我们所称的所有.NET平台上都是一致的,包括完整框架、核心、Xamarin、Mono、Silverlight等等。
之前不能使用针对一个平台编译的DLL在另一个平台上运行的原因是该格式未指定API(一般而言)。因此,虽然它们都可以读取DLL,但如果存在,则可能会遇到类XYZ在一个平台上的命名空间A.B.C中,在另一个平台上则在命名空间D.E.F中,或者根本不存在。
PCL通过执行两个操作来“解决”这个问题:
它们使用类型转发(Type Forwarding),因此即使您编写的代码期望在命名空间A.B.C中找到类XYZ,也可以在其他具有不同命名空间的平台上找到。
它限制了您可以使用的API,仅限于您想要的所有平台共享的最低公共集。
将PCL转换为.NET Standard项目并不是由于输出格式而重新编译,而是由于包含的元数据(尤其是类型转发)。
因此,我认为本质上.NET Standard库与PCL库没有区别,除了它们在不同的标准化API集合上放置了一层,并且这些API可能实现不同的指针(类型转发)。

.NET Core当然是一个运行时环境,但我认为它与.NET Standard非常密切相关。我认为它除了实现.NET Standard API之外,没有任何特殊的关系。

在我看来,通常最好针对.NET Standard类库进行目标设置,因为这将跨多个平台兼容。如果你针对.NET Core进行目标设置,例如,在UWP中无法引用此程序集类型。你会看到这个:

enter image description here

然而,如果您正在纯 .NET Core 环境中工作,您可能会发现有一些特定于 .NET Core 运行时环境的 API 可用,因此需要直接针对 .NET Core。请参阅以下词汇表:https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/glossary.md

我也建议看一下https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/glossary.md,以更好地澄清事情 :) - shmuelie
2
我曾经与一个NetFX团队成员交谈过。他说,如果库的代码无法理解.NET Standard,那么基于.NET Standard的库将无法在每个平台上工作。例如,您可以编写.NET Standard代码来打开一个文件,在Windows上存在,但在Linux上不存在。Nuget不会告诉您刚刚安装的软件包与您的Xamarin Android项目不兼容。Nuget仍然允许您添加此软件包,因为您的项目也支持.NET Standard。这意味着您不能再依赖Nuget来检查软件包的兼容性。一个新的可怕世界即将到来! - Softlion
这就是为什么您需要选择正确的 .NET Standard 库版本以匹配您正在构建的平台。 - Christian Findlay

9
我相信这个资源可以回答你大部分的问题:

https://learn.microsoft.com/en-us/dotnet/articles/standard/library

.NET标准库是.NET API的正式规范,旨在在所有.NET运行时上可用。标准库的动机是在.NET生态系统中建立更大的统一性。
据我所知,其他库类型是特定于平台的,而.NET标准则是到某种程度上与平台无关的。
如果您希望在不同的平台上使用您的代码,那么.NET标准似乎是理想的选择,但请注意其他平台支持的.NET标准版本(请参见链接中的表格)。
希望这可以帮助您。

很多人没有意识到的是,.net标准共享运行时但不共享基类库。当您使用一个.net标准库时,您会将所需的System.* dlls引入您的应用程序中。这会导致部署大小的增加。而PCL或完整的.net dll则不会出现这种情况。 - trampster

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接