SDK 样式项目中的目标框架

以应用或库中的框架为目标时,需要指定想要向应用或库提供的 API 集。 使用目标框架名字对象 (TFM) 在项目文件中指定目标框架。

应用或库可以使用 .NET Standard 版本作为目标。 .NET Standard 版本表示所有 .NET 实现中的标准化 API 集。 例如,库可以使用 .NET Standard 1.6 作为目标,并获得对可使用相同基本代码跨 .NET Core 和 .NET Framework 工作的 API 的访问权限。

应用或库还能以一个特定 .NET 实现为目标,获得特定于实现的 API 的访问权限。 例如,面向 Xamarin.iOS 的应用(如 Xamarin.iOS10)有权访问 Xamarin 提供的适用于 iOS 10 的 iOS API 包装器;面向通用 Windows 平台 (UWP) 的应用(如 uap10.0)有权访问为运行 Windows 10 的设备编译的 API。

对于某些目标框架(例如 .NET Framework),API 由框架在系统上安装的程序集定义,并且可能包括应用程序框架 API(例如 ASP.NET)。

对于基于包的目标框架(例如 .NET 5+、.NET Core 和 .NET Standard),API 是由应用或库中包含的 NuGet 包定义的。

最新版本

下表定义了最常见的目标框架、如何引用这些框架,以及它们实现的 .NET Standard 版本。 这些目标框架版本是最新的稳定版本。 预发行版不会显示。 目标框架名字对象 (TFM) 是一个标准化令牌格式,用于指定 .NET 应用或库的目标框架。

目标框架 最新
稳定版本
目标框架名字对象 (TFM) 已实现
.NET Standard 版本
.NET 6 6 net6.0 空值
.NET 5 5 net5.0 空值
.NET Standard 2.1 netstandard2.1 空值
.NET Core 3.1 netcoreapp3.1 2.1
.NET Framework 4.8 net48 2.0

支持的目标框架

目标框架通常由 TFM 引用。 下表显示 .NET SDK 和 NuGet 客户端支持的目标框架。 等效项显示在括号内。 例如,win81 对于 netcore451 来说等效于 TFM。

目标 Framework TFM
.NET 5 及更高版本(和 .NET Core) netcoreapp1.0
netcoreapp1.1
netcoreapp2.0
netcoreapp2.1
netcoreapp2.2
netcoreapp3.0
netcoreapp3.1
net5.0*
net6.0*
.NET Standard netstandard1.0
netstandard1.1
netstandard1.2
netstandard1.3
netstandard1.4
netstandard1.5
netstandard1.6
netstandard2.0
netstandard2.1
.NET Framework net11
net20
net35
net40
net403
net45
net451
net452
net46
net461
net462
net47
net471
net472
net48
Windows 应用商店 netcore [netcore45]
netcore45 [win] [win8]
netcore451 [win81]
.NET Micro Framework netmf
Silverlight sl4
sl5
Windows Phone wp [wp7]
wp7
wp75
wp8
wp81
wpa81
通用 Windows 平台 uap [uap10.0]
uap10.0 [win10] [netcore50]

* .NET 5 及更高版本的 TFM 包含一些特定于操作系统的变体。 有关详细信息,请参阅下一节:.NET 5 及更高版本特定于 OS 的 TFM

.NET 5 及更高版本特定于 OS 的 TFM

net5.0net6.0 TFM 包括可在不同平台中使用的技术。 指定特定于 OS 的 TFM 使特定于操作系统的 API 可供你的应用(例如 Windows 窗体或 iOS 绑定)使用。 特定于 OS 的 TFM 还会继承其基础 TFM(例如 net5.0 TFM)可用的每个 API。

.NET 5 引入了 net5.0-windows 特定于 OS 的 TFM,其中包括适用于 WinForms、WPF 和 UWP API 的特定于 Windows 的绑定。 .NET 6 引入了更多特定于 OS 的 TFM。

下表说明了 .NET 5 及更高版本 TFM 的兼容性。

TFM 可兼容对象
net5.0 net1..4(带有 NU1701 警告)
netcoreapp1..3.1 (引用 WinForms 或 WPF 时出现警告)
netstandard1..2.1
net5.0-windows netcoreapp1..3.1(以及从 net5.0 继承的所有其他内容)
net6.0 (后续版本的 net5.0
net6.0-android xamarin.android(以及从 net6.0 继承的所有其他内容)
net6.0-ios xamarin.ios(以及从 net6.0 继承的所有其他内容)
net6.0-macos xamarin.mac(以及从 net6.0 继承的所有其他内容)
net6.0-maccatalyst xamarin.ios(以及从 net6.0 继承的所有其他内容)
net6.0-tvos xamarin.tvos(以及从 net6.0 继承的所有其他内容)
net6.0-windows (后续版本的 net5.0-windows

若要使应用可跨不同平台移植,但仍有权访问特定于 OS 的 API,你可以定位多个特定于 OS 的 TFM,并使用 #if 预处理器指令围绕特定于 OS 的 API 调用增加平台防护。

建议的目标

使用以下准则确定在应用中使用哪种 TFM:

  • 可移植到多个平台的应用应面向基础 TFM,例如 net5.0。 这包括大多数库,但也包含 ASP.NET Core 和实体框架。

  • 特定于平台的库应面向特定于平台的风格。 例如,WinForms 和 WPF 项目应面向 net5.0-windowsnet6.0-windows

  • 跨平台应用模型(Xamarin Forms、ASP.NET Core)和网桥包 (Xamarin Essentials) 应至少面向基础 TFM(例如 net6.0),但也可以面向其他特定于平台的风格来支持更多的 API 或功能。

TFM 中的 OS 版本

你还可以在 OS 特定的 TFM 的末尾指定可选的 OS 版本,例如,net6.0-ios15.0。 版本指示应用或库可用的 API。 它不控制应用或库在运行时支持的 OS 版本。 它用于选择项目编译的引用程序集,并用于从 NuGet 包中选择资产。 将此版本视为“平台版本”或“OS API 版本”,可以与运行时 OS 版本进行区分。

当特定于 OS 的 TFM 不显式指定平台版本时,它具有可从基础 TFM 和平台名称推断的隐含值。 例如,.NET 6 中 iOS 的默认平台值为 15.0,这意味着 net6.0-ios 是规范 net6.0-ios15.0 TFM 的简写形式。 较新的基础 TFM 的隐含平台版本可能更高,例如,将来的 net7.0-ios TFM 可以映射到 net7.0-ios16.0。 简写形式仅用于项目文件,在传递给其他工具(如 NuGet)之前,.NET SDK 的 MSBuild 目标将其扩展为规范格式。

.NET SDK 设计为能够支持单个平台的新发布的 API,而无需使用新版本的基础 TFM。 这样,你无需等待 .NET 的主要版本就能访问特定于平台的功能。 可以通过在 TFM 中增加平台版本来访问这些新发布的 API。 例如,如果 iOS 平台在 .NET 6.0.x SDK 更新中添加了 iOS 15.1 API,你可以使用 TFM net6.0-ios15.1 访问它们。

支持旧版 OS

虽然特定于平台的应用或库是针对特定版本的 OS 中的 API 编译的,但你可以通过将 SupportedOSPlatformVersion 属性添加到项目文件,使其与早期版本的 OS 兼容。 SupportedOSPlatformVersion 属性指示运行应用或库所需的最低 OS 版本。 如果不在项目中显式指定此最低运行时 OS 版本,则默认为 TFM 中的平台版本。

若要使应用在较旧的 OS 版本上正常运行,它不能调用该 OS 版本上不存在的 API。 但是,可以增加对较新 API 的调用的防护,以便只有在支持这些 API 的 OS 版本上运行时,才能调用它们。 使用此模式可以设计应用或库,以支持在较旧的 OS 版本上运行,同时在较新的 OS 版本上运行时利用较新的 OS 功能。

SupportedOSPlatformVersion 值(无论是显式还是默认)由平台兼容性分析器使用,用于检测并警告对较新 API 的无防御调用。 它作为 UnsupportedOSPlatformAttribute 程序集属性记录到项目的编译程序集中,使平台兼容性分析器可以从具有较低值 SupportedOSPlatformVersion 的项目中检测对该程序集 API 的无防御调用。 在一些平台上,SupportedOSPlatformVersion 值会影响特定于平台的应用打包和生成过程,这些平台的文档对此有所介绍。

下面是一个项目文件的示例摘录,该文件使用 TargetFrameworkSupportedOSPlatformVersion MSBuild 属性指定应用或库有权访问 iOS 15.0 API,但支持在 iOS 13.0 及更高版本上运行:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0-ios15.0</TargetFramework>
    <SupportedOSPlatformVersion>13.0</SupportedOSPlatformVersion>
  </PropertyGroup>

  ...

</Project>

如何指定目标框架

在项目文件中指定目标框架。 指定单个目标框架时,使用 TargetFramework 元素。 以下控制台应用项目文件演示了如何面向 .NET 5:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

指定多个目标框架时,可有条件地为每个目标框架引用程序集。 在代码中,可使用具有 -if-then-else 逻辑的预处理器符号,有条件地针对这些程序集进行编译。

以下库项目面向 .NET Standard (netstandard1.4) 和 .NET Framework(net40net45)的 API。 将复数形式的 TargetFrameworks 元素与多个目标框架一起使用。 为两个 .NET Framework TFM 编译库时,Condition 属性包括特定于实现的包:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard1.4;net40;net45</TargetFrameworks>
  </PropertyGroup>

  <!-- Conditionally obtain references for the .NET Framework 4.0 target -->
  <ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
    <Reference Include="System.Net" />
  </ItemGroup>

  <!-- Conditionally obtain references for the .NET Framework 4.5 target -->
  <ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Threading.Tasks" />
  </ItemGroup>

</Project>

在库或应用中,使用预处理器指令编写条件代码,针对每个目标框架进行编译:

public class MyClass
{
    static void Main()
    {
#if NET40
        Console.WriteLine("Target framework: .NET Framework 4.0");
#elif NET45
        Console.WriteLine("Target framework: .NET Framework 4.5");
#else
        Console.WriteLine("Target framework: .NET Standard 1.4");
#endif
    }
}

使用 SDK 样式项目时,生成系统可识别预处理器符号,这些符号表示支持的目标框架版本表中所示的目标框架。 使用表示 .NET Standard、.NET Core 或 .NET 5 及更高版本 TFM 的符号时,请用下划线替换点和连字符,并将小写字母更改为大写字母(例如,netstandard1.4 的符号为 NETSTANDARD1_4)。 可以通过 DisableImplicitFrameworkDefines 属性禁止生成这些符号。 有关此属性的详细信息,请参阅 DisableImplicitFrameworkDefines

.NET 目标框架的预处理器符号的完整列表如下:

目标框架 符号 .NET 5 及更高版本 SDK 中可用的其他符号
.NET Framework NETFRAMEWORK, NET48, NET472, NET471, NET47, NET462, NET461, NET46, NET452, NET451, NET45, NET40, NET35, NET20 NET48_OR_GREATER, NET472_OR_GREATER, NET471_OR_GREATER, NET47_OR_GREATER, NET462_OR_GREATER, NET461_OR_GREATER, NET46_OR_GREATER, NET452_OR_GREATER, NET451_OR_GREATER, NET45_OR_GREATER, NET40_OR_GREATER, NET35_OR_GREATER, NET20_OR_GREATER
.NET Standard NETSTANDARD, NETSTANDARD2_1, NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2, NETSTANDARD1_1, NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER, NETSTANDARD2_0_OR_GREATER, NETSTANDARD1_6_OR_GREATER, NETSTANDARD1_5_OR_GREATER, NETSTANDARD1_4_OR_GREATER, NETSTANDARD1_3_OR_GREATER, NETSTANDARD1_2_OR_GREATER, NETSTANDARD1_1_OR_GREATER, NETSTANDARD1_0_OR_GREATER
.NET 5 及更高版本(和 .NET Core) NET, NET6_0, NET5_0, NETCOREAPP, NETCOREAPP3_1, NETCOREAPP3_0, NETCOREAPP2_2, NETCOREAPP2_1, NETCOREAPP2_0, NETCOREAPP1_1, NETCOREAPP1_0 NET6_0_OR_GREATER, NET5_0_OR_GREATER, NETCOREAPP3_1_OR_GREATER, NETCOREAPP3_0_OR_GREATER, NETCOREAPP2_2_OR_GREATER, NETCOREAPP2_1_OR_GREATER, NETCOREAPP2_0_OR_GREATER, NETCOREAPP1_1_OR_GREATER, NETCOREAPP1_0_OR_GREATER

注意

  • 无论目标版本是什么,都将定义无版本符号。
  • 仅针对目标版本定义特定于版本的符号。
  • 为目标版本和所有早期版本定义 <framework>_OR_GREATER 符号。 例如,如果针对 .NET Framework 2.0,则会定义以下符号:NET20NET20_OR_GREATERNET11_OR_GREATERNET10_OR_GREATER
  • 它们与 MSBuild TargetFramework 属性NuGet 使用的目标框架名字对象 (TFM) 不同。

已弃用的目标框架

以下目标框架已弃用。 面向这些目标框架的包应迁移到指定的替代框架。

已弃用的 TFM Replacement
aspnet50
aspnetcore50
dnxcore50
dnx
dnx45
dnx451
dnx452
netcoreapp
dotnet
dotnet50
dotnet51
dotnet52
dotnet53
dotnet54
dotnet55
dotnet56
netstandard
netcore50 uap10.0
win netcore45
win8 netcore45
win81 netcore451
win10 uap10.0
winrt netcore45

另请参阅