.NET Core 3.0 的新增功能What's new in .NET Core 3.0

本文介绍了 .NET Core 3.0 中的新增功能。This article describes what is new in .NET Core 3.0. 最大的增强功能之一是对 Windows 桌面应用程序的支持(仅限 Windows)。One of the biggest enhancements is support for Windows desktop applications (Windows only). 通过使用 .NET Core 3.0 SDK Windows 桌面组件,可移植 Windows 窗体和 Windows Presentation Foundation (WPF) 应用程序。By using the .NET Core 3.0 SDK component Windows Desktop, you can port your Windows Forms and Windows Presentation Foundation (WPF) applications. 明确地说,只有在 Windows 上才支持和包含 Windows 桌面组件。To be clear, the Windows Desktop component is only supported and included on Windows. 有关详细信息,请参阅本文后面的 Windows 桌面部分。For more information, see the Windows desktop section later in this article.

.NET Core 3.0 添加了对 C#8.0 的支持。.NET Core 3.0 adds support for C# 8.0. 强烈建议使用 Visual Studio 2019 版本 16.3 或更高版本、Visual Studio for Mac 8.3 或更高版本,或具有最新 C# 扩展的 Visual Studio CodeIt's highly recommended that you use Visual Studio 2019 version 16.3 or newer, Visual Studio for Mac 8.3 or newer, or Visual Studio Code with the latest C# extension.

立即在 Windows、macOS 或 Linux 上下载并开始使用 .NET Core 3.0Download and get started with .NET Core 3.0 right now on Windows, macOS, or Linux.

有关版本的详细信息,请参阅 .NET Core 3.0 公告For more information about the release, see the .NET Core 3.0 announcement.

Microsoft 认为 .NET Core RC1 可用于生产环境,且该软件完全受支持。.NET Core RC1 was considered production ready by Microsoft and was fully supported. 如果使用的是预览版本,则必须转换为 RTM 版本才能继续获得支持。If you're using a preview release, you must move to the RTM version for continued support.

语言改进 C# 8.0Language improvements C# 8.0

C# 8.0 也是该发布的一部分,包含可为空引用类型功能、异步流更多模式C# 8.0 is also part of this release, which includes the nullable reference types feature, async streams, and more patterns. 有关 C# 8.0 功能的详细信息,请参阅 C# 8.0 中的新增功能For more information about C# 8.0 features, see What's new in C# 8.0.

添加了语言增强功能,以支持下面详细说明的 API 功能:Language enhancements were added to support the following API features detailed below:

.NET Standard 2.1.NET Standard 2.1

.NET Core 3.0 已实现 .NET Standard 2.1 。.NET Core 3.0 implements .NET Standard 2.1. 但是,默认的 dotnet new classlib 模板还是会生成一个面向 .NET Standard 2.0 的项目 。However, the default dotnet new classlib template generates a project that still targets .NET Standard 2.0. 若要面向 .NET Standard 2.1,请编辑项目文件并将 TargetFramework 属性更改为 netstandard2.1To target .NET Standard 2.1, edit your project file and change the TargetFramework property to netstandard2.1:

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

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
  </PropertyGroup>

</Project>

如果使用 Visual Studio,则需要 Visual Studio 2019,这是因为 Visual Studio 2017 不支持 .NET Standard 2.1 或 .NET Core 3.0 。If you're using Visual Studio, you need Visual Studio 2019, as Visual Studio 2017 doesn't support .NET Standard 2.1 or .NET Core 3.0.

编译/部署Compile/Deploy

默认可执行文件Default executables

.NET Core 现在默认生成依赖于框架的可执行文件.NET Core now builds framework-dependent executables by default. 对于使用全局安装的 .NET Core 版本的应用程序而言,这是一种新行为。This behavior is new for applications that use a globally installed version of .NET Core. 以前,仅独立部署会生成可执行文件。Previously, only self-contained deployments would produce an executable.

dotnet builddotnet publish 期间,将创建一个与你使用的 SDK 的环境和平台相匹配的可执行文件。During dotnet build or dotnet publish, an executable is created that matches the environment and platform of the SDK you're using. 和其他本机可执行文件一样,可以使用这些可执行文件执行相同操作,例如:You can expect the same things with these executables as you would other native executables, such as:

  • 可以双击可执行文件。You can double-click on the executable.
  • 可以直接从命令提示符启用应用程序,如 Windows 上的 myapp.exe,以及 Linux 和 macOS 上的 ./myappYou can launch the application from a command prompt directly, such as myapp.exe on Windows, and ./myapp on Linux and macOS.

单文件可执行文件Single-file executables

dotnet publish 命令支持将应用打包为特定于平台的单文件可执行文件。The dotnet publish command supports packaging your app into a platform-specific single-file executable. 该可执行文件是自解压缩文件,包含运行应用所需的所有依赖项(包括本机依赖项)。The executable is self-extracting and contains all dependencies (including native) that are required to run your app. 首次运行应用时,应用程序将根据应用名称和生成标识符自解压缩到一个目录中。When the app is first run, the application is extracted to a directory based on the app name and build identifier. 再次运行应用程序时,启动速度将变快。Startup is faster when the application is run again. 除非使用了新版本,否则应用程序无需再次进行自解压缩。The application doesn't need to extract itself a second time unless a new version was used.

若要发布单文件可执行文件,请使用 dotnet publish 命令在项目或命令行中设置 PublishSingleFileTo publish a single-file executable, set the PublishSingleFile in your project or on the command line with the dotnet publish command:

<PropertyGroup>
  <RuntimeIdentifier>win10-x64</RuntimeIdentifier>
  <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>

-或--or-

dotnet publish -r win10-x64 -p:PublishSingleFile=true

有关单文件发布的详细信息,请参阅单文件捆绑程序设计文档For more information about single-file publishing, see the single-file bundler design document.

程序集链接Assembly linking

.NET core 3.0 SDK 随附了一种工具,可以通过分析 IL 并剪裁未使用的程序集来减小应用的大小。The .NET core 3.0 SDK comes with a tool that can reduce the size of apps by analyzing IL and trimming unused assemblies.

自包含应用包括运行代码所需的所有内容,而无需在主计算机上安装 .NET。Self-contained apps include everything needed to run your code, without requiring .NET to be installed on the host computer. 但是,很多时候应用只需要一小部分框架即可运行,并且可以删除其他未使用的库。However, many times the app only requires a small subset of the framework to function, and other unused libraries could be removed.

.NET Core 现在包含一个设置,将使用 IL 链接器工具扫描应用的 IL。.NET Core now includes a setting that will use the IL linker tool to scan the IL of your app. 此工具将检测哪些代码是必需的,然后剪裁未使用的库。This tool detects what code is required, and then trims unused libraries. 此工具可以显著减少某些应用的部署大小。This tool can significantly reduce the deployment size of some apps.

要启用此工具,请使用项目中的 <PublishTrimmed> 设置并发布自包含应用:To enable this tool, add the <PublishTrimmed> setting in your project and publish a self-contained app:

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
dotnet publish -r <rid> -c Release

例如,包含的基本“hello world”新控制台项目模板在发布时命中大小约为 70 MB。As an example, the basic "hello world" new console project template that is included, when published, hits about 70 MB in size. 通过使用 <PublishTrimmed>,其大小将减少到约 30 MB。By using <PublishTrimmed>, that size is reduced to about 30 MB.

请务必考虑到使用反射或相关动态功能的应用程序或框架(包括 ASP.NET Core 和 WPF)通常会在剪裁时损坏。It's important to consider that applications or frameworks (including ASP.NET Core and WPF) that use reflection or related dynamic features, will often break when trimmed. 发生此损坏是因为链接器不知道此动态行为,并且不能确定反射需要哪些框架类型。This breakage occurs because the linker doesn't know about this dynamic behavior and can't determine which framework types are required for reflection. 可配置 IL 链接器工具以发现这种情况。The IL Linker tool can be configured to be aware of this scenario.

最重要的是,剪裁后务必对应用进行测试。Above all else, be sure to test your app after trimming.

有关 IL 链接器工具的详细信息,请参阅文档,或访问 mono/linker 存储库。For more information about the IL Linker tool, see the documentation or visit the mono/linker repo.

分层编译Tiered compilation

.NET Core 3.0 中默认启用了分层编译 (TC)。Tiered compilation (TC) is on by default with .NET Core 3.0. 此功能使运行时能够更适应地使用实时 (JIT) 编译器来获得更好的性能。This feature enables the runtime to more adaptively use the Just-In-Time (JIT) compiler to get better performance.

TC 的主要优势是使(重新)实时编译方法能够要么牺牲代码质量以更快地生成代码,要么以较慢的速度生成更高质量的代码。The main benefit of TC is to enable (re-)jitting methods with a lower-quality-but-faster tier or a higher-quality-but-slower tier. 这有助于提高应用程序在从启动到稳定状态的各个执行阶段的性能。This helps increase performance of an application as it goes through various stages of execution, from startup through steady-state. 这与非 TC 方法完全不同,其中每种方法均以单一方式进行编译(与高质量层相同),这种方法偏向于稳定状态而不是启动性能。This contrasts with the non-TC approach, where every method is compiled a single way (the same as the high-quality tier), which is biased to steady-state over startup performance.

启用 TC 后,在启动调用的方法期间:When TC is enabled, during startup for a method that is called:

  • 如果该方法具有 AOT 编译的代码 (ReadyToRun),将使用预生成的代码。If the method has AOT-compiled code (ReadyToRun), the pregenerated code will be used.
  • 否则,将实时编译该方法。Otherwise, the method will be jitted. 一般来说,这些方法目前是值类型的泛型。Typically, these methods currently are generics over value types.
    • 快速 JIT 可以更快地生成较低质量的代码。Quick JIT produces lower-quality code more quickly. 在 .NET Core 3.0 中默认为不包含循环的方法启用了快速 JIT,并且该方法在启动过程中作为首选方法。Quick JIT is enabled by default in .NET Core 3.0 for methods that do not contain loops and is preferred during startup.
    • 完全优化的 JIT 可生成更高质量的代码,但速度更慢。The fully-optimizing JIT produces higher-quality code more slowly. 对于不使用快速 JIT 的方法(例如,如果该方法具有 [MethodImpl(MethodImplOptions.AggressiveOptimization)] 特性),则使用完全优化的 JIT。For methods where Quick JIT would not be used (for example, if the method is attributed with [MethodImpl(MethodImplOptions.AggressiveOptimization)]), the fully-optimizing JIT is used.

在调用方法数次后,最终将使用完全优化的 JIT 在后台重新实时编译这些方法。Eventually, after methods are called a number of times, they are re-jitted with the fully-optimizing JIT in the background.

通过快速 JIT 生成的代码可能会运行较慢、分配更多内存或使用更多堆栈空间。Code generated by Quick JIT may run slower, allocate more memory, or use more stack space. 如果出现问题,可以使用项目文件中的此设置禁用快速 JIT:If there are issues, Quick JIT may be disabled using this setting in your project file:

<PropertyGroup>
  <TieredCompilationQuickJit>false</TieredCompilationQuickJit>
</PropertyGroup>

若要完全禁用 TC,请在项目文件中使用此设置:To disable TC completely, use this setting in your project file:

<PropertyGroup>
  <TieredCompilation>false</TieredCompilation>
</PropertyGroup>

对项目文件中的上述设置所做的任何更改都可能需要反映清理生成(删除 objbin 目录并重新生成)。Any changes to the above settings in the project file may require a clean build to be reflected (delete the obj and bin directories and rebuild).

ReadyToRun 映像ReadyToRun images

可以通过将应用程序集编译为 ReadyToRun (R2R) 格式来改进.NET Core 应用程序的启动时间。You can improve the startup time of your .NET Core application by compiling your application assemblies as ReadyToRun (R2R) format. R2R 是一种预先 (AOT) 编译形式。R2R is a form of ahead-of-time (AOT) compilation.

R2R 二进制文件通过减少应用程序加载时实时 (JIT) 编译器需要执行的工作量来改进启动性能。R2R binaries improve startup performance by reducing the amount of work the just-in-time (JIT) compiler needs to do as your application loads. 二进制文件包含与 JIT 将生成的内容类似的本机代码。The binaries contain similar native code compared to what the JIT would produce. 但是,R2R 二进制文件更大,因为它们包含中间语言 (IL) 代码(某些情况下仍需要此代码)和相同代码的本机版本。However, R2R binaries are larger because they contain both intermediate language (IL) code, which is still needed for some scenarios, and the native version of the same code. 仅当发布面向特定运行时环境 (RID)(如 Linux x64 或 Windows x64)的自包含应用时 R2R 才可用。R2R is only available when you publish a self-contained app that targets specific runtime environments (RID) such as Linux x64 or Windows x64.

若要将项目编译为 ReadyToRun,请执行以下操作:To compile your project as ReadyToRun, do the following:

  1. 向项目中添加 <PublishReadyToRun> 设置:Add the <PublishReadyToRun> setting to your project:

    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
  2. 发布自包含应用。Publish a self-contained app. 例如,此命令将创建适用于 Windows 64 位版本的自包含应用:For example, this command creates a self-contained app for the 64-bit version of Windows:

    dotnet publish -c Release -r win-x64 --self-contained
    

跨平台/体系结构限制Cross platform/architecture restrictions

ReadyToRun 编译器当前不支持跨目标。The ReadyToRun compiler doesn't currently support cross-targeting. 必须在给定的目标上编译。You must compile on a given target. 例如,如果想要 Windows x64 R2R 映像,需要在该环境中运行发布命令。For example, if you want R2R images for Windows x64, you need to run the publish command on that environment.

跨目标的例外情况:Exceptions to cross-targeting:

  • 可以使用 Windows x64 编译 Windows ARM32、ARM64 和 x86 映像。Windows x64 can be used to compile Windows ARM32, ARM64, and x86 images.
  • 可以使用 Windows x86 编译 Windows ARM32 映像。Windows x86 can be used to compile Windows ARM32 images.
  • 可以使用 Linux x64 编译 Linux ARM32 和 ARM64 映像。Linux x64 can be used to compile Linux ARM32 and ARM64 images.

运行时/SDKRuntime/SDK

主要版本前滚Major-version Roll Forward

.NET Core 3.0 引入了一项选择加入功能,该功能允许应用前滚到 .NET Core 最新的主要版本。.NET Core 3.0 introduces an opt-in feature that allows your app to roll forward to the latest major version of .NET Core. 此外,还添加了一项新设置来控制如何将前滚应用于应用。Additionally, a new setting has been added to control how roll forward is applied to your app. 这可以通过以下方式配置:This can be configured in the following ways:

  • 项目文件属性:RollForwardProject file property: RollForward
  • 运行时配置文件属性:rollForwardRuntime configuration file property: rollForward
  • 环境变量:DOTNET_ROLL_FORWARDEnvironment variable: DOTNET_ROLL_FORWARD
  • 命令行参数:--roll-forwardCommand-line argument: --roll-forward

必须指定以下值之一。One of the following values must be specified. 如果省略该设置,则默认值为“Minor” 。If the setting is omitted, Minor is the default.

  • LatestPatchLatestPatch
    前滚到最高补丁版本。Roll forward to the highest patch version. 这会禁用次要版本前滚。This disables minor version roll forward.
  • MinorMinor
    如果缺少所请求的次要版本,则前滚到最低的较高次要版本。Roll forward to the lowest higher minor version, if requested minor version is missing. 如果存在所请求的次要版本,则使用 LatestPatch 策略。If the requested minor version is present, then the LatestPatch policy is used.
  • MajorMajor
    如果缺少所请求的主要版本,则前滚到最低的较高主要版本和最低的次要版本。Roll forward to lowest higher major version, and lowest minor version, if requested major version is missing. 如果存在所请求的主要版本,则使用 Minor 策略。If the requested major version is present, then the Minor policy is used.
  • LatestMinorLatestMinor
    即使存在所请求的次要版本,仍前滚到最高次要版本。Roll forward to highest minor version, even if requested minor version is present. 适用于组件托管方案。Intended for component hosting scenarios.
  • LatestMajorLatestMajor
    即使存在所请求的主要版本,仍前滚到最高主要版本和最高次要版本。Roll forward to highest major and highest minor version, even if requested major is present. 适用于组件托管方案。Intended for component hosting scenarios.
  • DisableDisable
    不前滚。Don't roll forward. 仅绑定到指定的版本。Only bind to specified version. 建议不要将此策略用于一般用途,因为它会禁用前滚到最新补丁的功能。This policy isn't recommended for general use because it disables the ability to roll forward to the latest patches. 该值仅建议用于测试。This value is only recommended for testing.

除“Disable”设置外,所有设置都将使用可用的最高补丁版本 。Besides the Disable setting, all settings will use the highest available patch version.

生成会复制依赖项Build copies dependencies

dotnet build 命令现在将应用程序的 NuGet 依赖项从 NuGet 缓存复制到生成输出文件夹。The dotnet build command now copies NuGet dependencies for your application from the NuGet cache to the build output folder. 此前,依赖项仅作为 dotnet publish 的一部分复制。Previously, dependencies were only copied as part of dotnet publish.

有些操作,比如链接和 razor 页面发布仍需要发布。There are some operations, like linking and razor page publishing that will still require publishing.

本地工具Local tools

.NET Core 3.0 引入了本地工具。.NET Core 3.0 introduces local tools. 本地工具类似于全局工具,但与磁盘上的特定位置相关联。Local tools are similar to global tools but are associated with a particular location on disk. 本地工具在全局范围内不可用,并作为 NuGet 包进行分发。Local tools aren't available globally and are distributed as NuGet packages.

警告

如果尝试使用过 .NET Core 3.0 预览版 1 中的本地工具,例如运行 dotnet tool restoredotnet tool install,请删除本地工具缓存文件夹。If you tried local tools in .NET Core 3.0 Preview 1, such as running dotnet tool restore or dotnet tool install, delete the local tools cache folder. 否则,本地工具将无法在任何较新的版本上运行。Otherwise, local tools won't work on any newer release. 此文件夹位于:This folder is located at:

在 macOS、Linux 上:rm -r $HOME/.dotnet/toolResolverCacheOn macOS, Linux: rm -r $HOME/.dotnet/toolResolverCache

在 Windows 上:rmdir /s %USERPROFILE%\.dotnet\toolResolverCacheOn Windows: rmdir /s %USERPROFILE%\.dotnet\toolResolverCache

本地工具依赖于当前目录中名为 dotnet-tools.json 的清单文件。Local tools rely on a manifest file name dotnet-tools.json in your current directory. 此清单文件定义在该文件夹和以下文件夹中可用的工具。This manifest file defines the tools to be available at that folder and below. 你可以随代码一起分发清单文件,以确保使用代码的任何人都可以还原和使用相同的工具。You can distribute the manifest file with your code to ensure that anyone who works with your code can restore and use the same tools.

对于全局工具和本地工具,需要一个兼容的运行时版本。For both global and local tools, a compatible version of the runtime is required. 目前,NuGet.org 上的许多工具都面向 .NET Core Runtime 2.1。Many tools currently on NuGet.org target .NET Core Runtime 2.1. 若要在全局范围或本地安装这些工具,仍需要安装 NET Core 2.1 运行时To install these tools globally or locally, you would still need to install the NET Core 2.1 Runtime.

垃圾回收堆大小减小Smaller Garbage Collection heap sizes

垃圾回收器的默认堆大小已减小,以使 .NET Core 使用更少的内存。The Garbage Collector's default heap size has been reduced resulting in .NET Core using less memory. 此更改更符合具有现代处理器缓存大小的第 0 代分配预算。This change better aligns with the generation 0 allocation budget with modern processor cache sizes.

垃圾回收大型页面支持Garbage Collection Large Page support

大型页面(也称为 Linux 上的巨型页面)是一项功能,其中操作系统能够建立大于本机页面大小(通常为 4K)的内存区域,以提高请求这些大型页面的应用程序的性能。Large Pages (also known as Huge Pages on Linux) is a feature where the operating system is able to establish memory regions larger than the native page size (often 4K) to improve performance of the application requesting these large pages.

现在可以使用 GCLargePages 设置将垃圾回收器配置为一项选择加入功能,以选择在 Windows 上分配大型页面。The Garbage Collector can now be configured with the GCLargePages setting as an opt-in feature to choose to allocate large pages on Windows.

Windows 桌面和 COMWindows Desktop & COM

.NET Core SDK Windows Installer.NET Core SDK Windows Installer

用于 Windows 的 MSI 安装程序已从 .NET Core 3.0 开始更改。The MSI installer for Windows has changed starting with .NET Core 3.0. SDK 安装程序现在将对 SDK 功能区段版本进行就地升级。The SDK installers will now upgrade SDK feature-band releases in place. 功能区段在版本号的补丁部分中的百数组中定义。Feature bands are defined in the hundreds groups in the patch section of the version number. 例如,3.0.1013.0.201 是两个不同功能区段中的版本,而 3.0.1013.0.199 则属于同一个功能区段。 For example, 3.0.101 and 3.0.201 are versions in two different feature bands while 3.0.101 and 3.0.199 are in the same feature band. 并且,当安装 .NET Core SDK 3.0.101 时,将从计算机中删除 .NET Core SDK 3.0.100 (如果存在)。 And, when .NET Core SDK 3.0.101 is installed, .NET Core SDK 3.0.100 will be removed from the machine if it exists. 当 .NET Core SDK 3.0.200 安装在同一台计算机上时,不会删除 .NET Core SDK 3.0.101When .NET Core SDK 3.0.200 is installed on the same machine, .NET Core SDK 3.0.101 won't be removed.

有关版本控制的详细信息,请参阅 .NET Core 的版本控制方式概述For more information about versioning, see Overview of how .NET Core is versioned.

Windows 桌面Windows desktop

.NET Core 3.0 支持使用 Windows Presentation Foundation (WPF) 和 Windows 窗体的 Windows 桌面应用程序。.NET Core 3.0 supports Windows desktop applications using Windows Presentation Foundation (WPF) and Windows Forms. 这些框架还支持通过 XAML 岛从 Windows UI XAML 库 (WinUI) 使用新式控件和 Fluent 样式。These frameworks also support using modern controls and Fluent styling from the Windows UI XAML Library (WinUI) via XAML islands.

Windows 桌面部件是 Windows .NET Core 3.0 SDK 的一部分。The Windows Desktop component is part of the Windows .NET Core 3.0 SDK.

可以使用以下 dotnet 命令创建新的 WPF 或 Windows 窗体应用:You can create a new WPF or Windows Forms app with the following dotnet commands:

dotnet new wpf
dotnet new winforms

Visual Studio 2019 添加了适用于 .NET Core 3.0 Windows 窗体和 WPF 的“新建项目” 模板。Visual Studio 2019 adds New Project templates for .NET Core 3.0 Windows Forms and WPF.

有关如何移植现有 .NET Framework 应用程序的详细信息,请参阅移植 WPF 项目移植 Windows 窗体项目For more information about how to port an existing .NET Framework application, see Port WPF projects and Port Windows Forms projects.

WinForms 高 DPIWinForms high DPI

.NET Core Windows 窗体应用程序可以使用 Application.SetHighDpiMode(HighDpiMode) 设置高 DPI 模式。.NET Core Windows Forms applications can set high DPI mode with Application.SetHighDpiMode(HighDpiMode). SetHighDpiMode 方法可设置相应的高 DPI 模式,除非该设置已通过其他方式(例如使用 App.Manifest 或在 Application.Run 前面使用 P/Invoke)进行设置。The SetHighDpiMode method sets the corresponding high DPI mode unless the setting has been set by other means like App.Manifest or P/Invoke before Application.Run.

System.Windows.Forms.HighDpiMode 枚举表示的可能的 highDpiMode 值包括:The possible highDpiMode values, as expressed by the System.Windows.Forms.HighDpiMode enum are:

  • DpiUnaware
  • SystemAware
  • PerMonitor
  • PerMonitorV2
  • DpiUnawareGdiScaled

有关高 DPI 模式的详细信息,请参阅在 Windows 上开发高 DPI 桌面应用程序For more information about high DPI modes, see High DPI Desktop Application Development on Windows.

创建 COM 组件Create COM components

在 Windows 上,现在可以创建可调用 COM 的托管组件。On Windows, you can now create COM-callable managed components. 在将 .NET Core 与 COM 加载项模型结合使用,以及使用 .NET Framework 提供奇偶校验时,此功能至关重要。This capability is critical to use .NET Core with COM add-in models and also to provide parity with .NET Framework.

与将 mscoree.dll 用作 COM 服务器的 .NET Framework 不同,.NET Core 将在生成 COM 组件时向 bin 目录添加本机启动程序 dll。Unlike .NET Framework where the mscoree.dll was used as the COM server, .NET Core will add a native launcher dll to the bin directory when you build your COM component.

有关如何创建 COM 组件并使用它的示例,请参阅 COM 演示For an example of how to create a COM component and consume it, see the COM Demo.

Windows 本机互操作Windows Native Interop

Windows 提供丰富的本机 API,包括平面 C API、COM 和 WinRT 的形式。Windows offers a rich native API in the form of flat C APIs, COM, and WinRT. .NET Core 支持 P/Invoke, .NET Core 3.0 则增加了 CoCreate COM APIActivate WinRT API 的功能。While .NET Core supports P/Invoke, .NET Core 3.0 adds the ability to CoCreate COM APIs and Activate WinRT APIs. 有关代码示例,请参阅 Excel 演示For a code example, see the Excel Demo.

MSIX 部署MSIX Deployment

MSIX 是新的 Windows 应用程序包格式。MSIX is a new Windows application package format. 可以使用它将 .NET Core 3.0 桌面应用程序部署到 Windows 10。It can be used to deploy .NET Core 3.0 desktop applications to Windows 10.

使用 Visual Studio 2019 中的 Windows 应用打包项目,可以创建包含独立式 .NET Core 应用的 MSIX 包。The Windows Application Packaging Project, available in Visual Studio 2019, allows you to create MSIX packages with self-contained .NET Core applications.

.NET Core 项目文件必须在 <RuntimeIdentifiers> 属性中指定支持的运行时:The .NET Core project file must specify the supported runtimes in the <RuntimeIdentifiers> property:

<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>

Linux 改进Linux improvements

适用于 Linux 的 SerialPortSerialPort for Linux

.NET Core 3.0 提供对 Linux 上 System.IO.Ports.SerialPort 的基本支持。.NET Core 3.0 provides basic support for System.IO.Ports.SerialPort on Linux.

以前,.NET Core 只支持在 Windows 上使用 SerialPortPreviously, .NET Core only supported using SerialPort on Windows.

有关对 Linux 上串行端口有限支持的详细信息,请参阅 GitHub 问题 #33146For more information about the limited support for the serial port on Linux, see GitHub issue #33146.

Docker 和 cgroup 内存限制Docker and cgroup memory Limits

在 Linux 上使用 Docker 运行 .NET Core 3.0 时,可更好地应对 cgroup 内存限制。Running .NET Core 3.0 on Linux with Docker works better with cgroup memory limits. 运行具有内存限制的 Docker 容器(例如使用 docker run -m)会更改 .NET Core 的行为方式。Running a Docker container with memory limits, such as with docker run -m, changes how .NET Core behaves.

  • 默认垃圾回收器 (GC) 堆大小:最大为 20 MB 或容器内存限制的 75%。Default Garbage Collector (GC) heap size: maximum of 20 mb or 75% of the memory limit on the container.
  • 可以将显式大小设置为绝对数或 cgroup 限制的百分比。Explicit size can be set as an absolute number or percentage of cgroup limit.
  • 每个 GC 堆的最小保留段大小为 16 MB。Minimum reserved segment size per GC heap is 16 mb. 此大小可减少在计算机上创建的堆数量。This size reduces the number of heaps that are created on machines.

对 Raspberry Pi 的 GPIO 支持GPIO Support for Raspberry Pi

已向 NuGet 发布了两个可用于 GPIO 编程的包:Two packages have been released to NuGet that you can use for GPIO programming:

GPIO 包包括用于 GPIOSPII2CPWM 设备的 API。The GPIO packages include APIs for GPIO, SPI, I2C, and PWM devices. IoT 绑定包包括设备绑定。The IoT bindings package includes device bindings. 有关详细信息,请参阅设备 GitHub 存储库For more information, see the devices GitHub repo.

ARM64 Linux 支持ARM64 Linux support

.NET Core 3.0 增加了对 ARM64 for Linux 的支持。.NET Core 3.0 adds support for ARM64 for Linux. ARM64 的主要用例是当前的 IoT 场景。The primary use case for ARM64 is currently with IoT scenarios. 有关详细信息,请参阅 .NET Core ARM64 状态For more information, see .NET Core ARM64 Status.

ARM64 上适用于 .NET Core 的 Docker 映像可用于 Alpine、Debian 和 Ubuntu。Docker images for .NET Core on ARM64 are available for Alpine, Debian, and Ubuntu.

备注

ARM64 尚未提供 Windows 支持。ARM64 Windows support isn't yet available.

安全性Security

Linux 上的 TLS 1.3 和 OpenSSL 1.1.1TLS 1.3 & OpenSSL 1.1.1 on Linux

.NET Core 现在可以在给定环境中使用 OpenSSL 1.1.1 中的 TLS 1.3 支持.NET Core now takes advantage of TLS 1.3 support in OpenSSL 1.1.1, when it's available in a given environment. 使用 TLS 1.3:With TLS 1.3:

  • 通过减少客户端和服务器之间所需的往返次数,提高了连接时间。Connection times are improved with reduced round trips required between the client and server.
  • 由于删除了各种过时和不安全的加密算法,提高了安全性。Improved security because of the removal of various obsolete and insecure cryptographic algorithms.

.NET Core 3.0 在 Linux 系统上使用 OpenSSL 1.1.1OpenSSL 1.1.0OpenSSL 1.0.2(如果可用)。When available, .NET Core 3.0 uses OpenSSL 1.1.1, OpenSSL 1.1.0, or OpenSSL 1.0.2 on a Linux system. OpenSSL 1.1.1 可用时,System.Net.Security.SslStreamSystem.Net.Http.HttpClient 类型都将使用 TLS 1.3(假定客户端和服务器都支持 TLS 1.3)。When OpenSSL 1.1.1 is available, both System.Net.Security.SslStream and System.Net.Http.HttpClient types will use TLS 1.3 (assuming both the client and server support TLS 1.3).

重要

Windows 和 macOS 尚不支持 TLS 1.3 。Windows and macOS do not yet support TLS 1.3. 当支持可用时,.NET Core 3.0 将在这些操作系统上支持 TLS 1.3 。.NET Core 3.0 will support TLS 1.3 on these operating systems when support becomes available.

下面的 C# 8.0 示例演示在 Ubuntu 18.10 上 .NET Core 3.0 如何连接到 https://www.cloudflare.comThe following C# 8.0 example demonstrates .NET Core 3.0 on Ubuntu 18.10 connecting to https://www.cloudflare.com:

using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace whats_new
{
    public static class TLS
    {
        public static async Task ConnectCloudFlare()
        {
            var targetHost = "www.cloudflare.com";

            using TcpClient tcpClient = new TcpClient();

            await tcpClient.ConnectAsync(targetHost, 443);

            using SslStream sslStream = new SslStream(tcpClient.GetStream());
            
            await sslStream.AuthenticateAsClientAsync(targetHost);
            await Console.Out.WriteLineAsync($"Connected to {targetHost} with {sslStream.SslProtocol}");
        }
    }
}

加密密码Cryptography ciphers

.NET 3.0 增加了对 AES-GCMAES-CCM 密码的支持(分别使用 System.Security.Cryptography.AesGcmSystem.Security.Cryptography.AesCcm 实现)。.NET 3.0 adds support for AES-GCM and AES-CCM ciphers, implemented with System.Security.Cryptography.AesGcm and System.Security.Cryptography.AesCcm respectively. 这些算法都是用于关联数据的认证加密 (AEAD) 算法These algorithms are both Authenticated Encryption with Association Data (AEAD) algorithms.

下面的代码演示了如何使用 AesGcm 密码加密和解密随机数据。The following code demonstrates using AesGcm cipher to encrypt and decrypt random data.

using System;
using System.Linq;
using System.Security.Cryptography;

namespace whats_new
{
    public static class Cipher
    {
        public static void Run()
        {
            // key should be: pre-known, derived, or transported via another channel, such as RSA encryption
            byte[] key = new byte[16];
            RandomNumberGenerator.Fill(key);

            byte[] nonce = new byte[12];
            RandomNumberGenerator.Fill(nonce);

            // normally this would be your data
            byte[] dataToEncrypt = new byte[1234];
            byte[] associatedData = new byte[333];
            RandomNumberGenerator.Fill(dataToEncrypt);
            RandomNumberGenerator.Fill(associatedData);

            // these will be filled during the encryption
            byte[] tag = new byte[16];
            byte[] ciphertext = new byte[dataToEncrypt.Length];

            using (AesGcm aesGcm = new AesGcm(key))
            {
                aesGcm.Encrypt(nonce, dataToEncrypt, ciphertext, tag, associatedData);
            }

            // tag, nonce, ciphertext, associatedData should be sent to the other part

            byte[] decryptedData = new byte[ciphertext.Length];

            using (AesGcm aesGcm = new AesGcm(key))
            {
                aesGcm.Decrypt(nonce, ciphertext, tag, decryptedData, associatedData);
            }

            // do something with the data
            // this should always print that data is the same
            Console.WriteLine($"AES-GCM: Decrypted data is {(dataToEncrypt.SequenceEqual(decryptedData) ? "the same as" : "different than")} original data.");
        }
    }
}

加密密钥导入/导出Cryptographic Key Import/Export

.NET Core 3.0 支持从标准格式导入和导出非对称公钥和私钥。.NET Core 3.0 supports the import and export of asymmetric public and private keys from standard formats. 你不需要使用 X.509 证书。You don't need to use an X.509 certificate.

所有密钥类型(例如 RSADSAECDsaECDiffieHellman)都支持以下格式:All key types, such as RSA, DSA, ECDsa, and ECDiffieHellman, support the following formats:

  • 公钥Public Key

    • X.509 SubjectPublicKeyInfoX.509 SubjectPublicKeyInfo
  • 私钥Private key

    • PKCS#8 PrivateKeyInfoPKCS#8 PrivateKeyInfo
    • PKCS#8 EncryptedPrivateKeyInfoPKCS#8 EncryptedPrivateKeyInfo

RSA 密钥还支持:RSA keys also support:

  • 公钥Public Key

    • PKCS#1 RSAPublicKeyPKCS#1 RSAPublicKey
  • 私钥Private key

    • PKCS#1 RSAPrivateKeyPKCS#1 RSAPrivateKey

导出方法生成 DER 编码的二进制数据,导入方法也是如此。The export methods produce DER-encoded binary data, and the import methods expect the same. 如果密钥以文本友好的 PEM 格式存储,调用方需要在调用导入方法之前对内容进行 base64 解码。If a key is stored in the text-friendly PEM format, the caller will need to base64-decode the content before calling an import method.

using System;
using System.Security.Cryptography;

namespace whats_new
{
    public static class RSATest
    {
        public static void Run(string keyFile)
        {
            using var rsa = RSA.Create();

            byte[] keyBytes = System.IO.File.ReadAllBytes(keyFile);
            rsa.ImportRSAPrivateKey(keyBytes, out int bytesRead);

            Console.WriteLine($"Read {bytesRead} bytes, {keyBytes.Length - bytesRead} extra byte(s) in file.");
            RSAParameters rsaParameters = rsa.ExportParameters(true);
            Console.WriteLine(BitConverter.ToString(rsaParameters.D));
        }
    }
}

可以使用 System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo 检查 PKCS#8 文件,使用 System.Security.Cryptography.Pkcs.Pkcs12Info 检查 PFX/PKCS#12 文件。PKCS#8 files can be inspected with System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo and PFX/PKCS#12 files can be inspected with System.Security.Cryptography.Pkcs.Pkcs12Info. 可以使用 System.Security.Cryptography.Pkcs.Pkcs12Builder 操作 PFX/PKCS#12 文件。PFX/PKCS#12 files can be manipulated with System.Security.Cryptography.Pkcs.Pkcs12Builder.

.NET Core 3.0 API 改动.NET Core 3.0 API changes

范围和索引Ranges and indices

System.Index 类型可用于编制索引。The new System.Index type can be used for indexing. 可从 int 创建一个从开头开始计数的索引,也可使用前缀 ^ 运算符 (C#) 创建一个从末尾开始计数的索引:You can create one from an int that counts from the beginning, or with a prefix ^ operator (C#) that counts from the end:

Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"

此外,还有 System.Range 类型,它包含两个 Index 值,一个用于开头一个用于结尾,可以使用 x..y 范围表达式 (C#) 进行编写。There's also the System.Range type, which consists of two Index values, one for the start and one for the end, and can be written with a x..y range expression (C#). 然后可以使用 Range 编制索引,以便生成一个切片:You can then index with a Range, which produces a slice:

var slice = a[i1..i2]; // { 3, 4, 5 }

有关详细信息,请参阅范围和索引教程For more information, see the ranges and indices tutorial.

异步流Async streams

IAsyncEnumerable<T> 类型是 IEnumerable<T> 的新异步版本。The IAsyncEnumerable<T> type is a new asynchronous version of IEnumerable<T>. 通过该语言,可通过 IAsyncEnumerable<T> 执行 await foreach 操作来使用其元素,并对其使用 yield return 操作来生成元素。The language lets you await foreach over IAsyncEnumerable<T> to consume their elements, and use yield return to them to produce elements.

下面的示例演示如何生成和使用异步流。The following example demonstrates both production and consumption of async streams. foreach 语句为异步语句,它本身使用 yield return 为调用方生成异步流。The foreach statement is async and itself uses yield return to produce an async stream for callers. 此模式(使用 yield return)是生成异步流的建议模型。This pattern (using yield return) is the recommended model for producing async streams.

async IAsyncEnumerable<int> GetBigResultsAsync()
{
    await foreach (var result in GetResultsAsync())
    {
        if (result > 20) yield return result;
    }
}

除了能够 await foreach,还可以创建异步迭代器,例如,一个返回 IAsyncEnumerable/IAsyncEnumerator 的迭代器,可以在其中进行 awaityield 操作。In addition to being able to await foreach, you can also create async iterators, for example, an iterator that returns an IAsyncEnumerable/IAsyncEnumerator that you can both await and yield in. 对于需要处理的对象,可以使用各种 BCL 类型(如 StreamTimer)实现的 IAsyncDisposableFor objects that need to be disposed, you can use IAsyncDisposable, which various BCL types implement, such as Stream and Timer.

有关详细信息,请参阅异步流教程For more information, see the async streams tutorial.

IEEE 浮点IEEE Floating-point

正在更新浮点 API,以符合 IEEE 754-2008 修订Floating point APIs are being updated to comply with IEEE 754-2008 revision. 这些更改旨在公开所有必需操作并确保这些操作在行为上符合 IEEE 规范。有关浮点改进的详细信息,请参阅 .NET Core 3.0 中的浮点分析和格式化改进博客文章。The goal of these changes is to expose all required operations and ensure that they're behaviorally compliant with the IEEE spec. For more information about floating-point improvements, see the Floating-Point Parsing and Formatting improvements in .NET Core 3.0 blog post.

分析和格式化修复包括:Parsing and formatting fixes include:

  • 正确分析并舍入任何输入长度。Correctly parse and round inputs of any length.
  • 正确分析并格式化负零。Correctly parse and format negative zero.
  • 通过执行不区分大小写的检查并允许在前面使用可选的 +(如果适用),正确分析 InfinityNaNCorrectly parse Infinity and NaN by doing a case-insensitive check and allowing an optional preceding + where applicable.

新的 System.Math API 包括:New System.Math APIs include:

  • BitIncrement(Double)BitDecrement(Double)BitIncrement(Double) and BitDecrement(Double)
    相当于 nextUpnextDown IEEE 运算。Corresponds to the nextUp and nextDown IEEE operations. 它们将返回最小的浮点数,该数字大于或小于输入值(分别)。They return the smallest floating-point number that compares greater or lesser than the input (respectively). 例如,Math.BitIncrement(0.0) 将返回 double.EpsilonFor example, Math.BitIncrement(0.0) would return double.Epsilon.

  • MaxMagnitude(Double, Double)MinMagnitude(Double, Double)MaxMagnitude(Double, Double) and MinMagnitude(Double, Double)
    相当于 maxNumMagminNumMag IEEE 运算,它们将(分别)返回大于或小于两个输入的量值的值。Corresponds to the maxNumMag and minNumMag IEEE operations, they return the value that is greater or lesser in magnitude of the two inputs (respectively). 例如,Math.MaxMagnitude(2.0, -3.0) 将返回 -3.0For example, Math.MaxMagnitude(2.0, -3.0) would return -3.0.

  • ILogB(Double)
    相当于返回整数值的 logB IEEE 运算,它将返回输入参数的整数对数(以 2 为底)。Corresponds to the logB IEEE operation that returns an integral value, it returns the integral base-2 log of the input parameter. 此方法实际上与 floor(log2(x)) 相同,但完成后出现最小舍入错误。This method is effectively the same as floor(log2(x)), but done with minimal rounding error.

  • ScaleB(Double, Int32)
    相当于采用整数值的 scaleB IEEE 运算,它实际返回 x * pow(2, n),但完成后出现最小舍入错误。Corresponds to the scaleB IEEE operation that takes an integral value, it returns effectively x * pow(2, n), but is done with minimal rounding error.

  • Log2(Double)
    相当于返回(以 2 为底)对数的 log2 IEEE 运算。Corresponds to the log2 IEEE operation, it returns the base-2 logarithm. 它会最小化舍入错误。It minimizes rounding error.

  • FusedMultiplyAdd(Double, Double, Double)
    相当于执行乘法加法混合的 fma IEEE 运算。Corresponds to the fma IEEE operation, it performs a fused multiply add. 也就是说,它以单个运算的形式执行 (x * y) + z,从而最小化舍入错误。That is, it does (x * y) + z as a single operation, thereby minimizing the rounding error. 有关示例是返回 1e308FusedMultiplyAdd(1e308, 2.0, -1e308)An example would be FusedMultiplyAdd(1e308, 2.0, -1e308) which returns 1e308. 常规 (1e308 * 2.0) - 1e308 返回 double.PositiveInfinityThe regular (1e308 * 2.0) - 1e308 returns double.PositiveInfinity.

  • CopySign(Double, Double)
    相当于 copySign IEEE 运算,它返回 x 的值但带有符号 yCorresponds to the copySign IEEE operation, it returns the value of x, but with the sign of y.

.NET 平台相关内部函数.NET Platform-Dependent Intrinsics

已添加 API,允许访问某些性能导向的 CPU 指令,例如 SIMD 或位操作指令集 。APIs have been added that allow access to certain perf-oriented CPU instructions, such as the SIMD or Bit Manipulation instruction sets. 这些指令有助于在某些情况下实现显著的性能改进,例如高效地并行处理数据。These instructions can help achieve significant performance improvements in certain scenarios, such as processing data efficiently in parallel.

在适当的情况下,.NET 库已开始使用这些指令来改进性能。Where appropriate, the .NET libraries have begun using these instructions to improve performance.

有关详细信息,请参阅 .NET Platform Dependent Intrinsics(.NET 平台相关内部函数)。For more information, see .NET Platform Dependent Intrinsics.

改进的 .NET Core 版本 APIImproved .NET Core Version APIs

从 .NET Core 3.0 开始,.NET Core 提供的版本 API 现在可以返回你预期的信息。Starting with .NET Core 3.0, the version APIs provided with .NET Core now return the information you expect. 例如:For example:

System.Console.WriteLine($"Environment.Version: {System.Environment.Version}");

// Old result
//   Environment.Version: 4.0.30319.42000
//
// New result
//   Environment.Version: 3.0.0
System.Console.WriteLine($"RuntimeInformation.FrameworkDescription: {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}");

// Old result
//   RuntimeInformation.FrameworkDescription: .NET Core 4.6.27415.71
//
// New result (notice the value includes any preview release information)
//   RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4-27615-11

警告

重大变更。Breaking change. 这在技术上是一个中断性变更,因为版本控制方案已发生变化。This is technically a breaking change because the versioning scheme has changed.

内置的快速 JSON 支持Fast built-in JSON support

.NET 用户在很大程度上依赖于 Json.NET 和其他常用的 JSON 库,它们仍是很好的选择。.NET users have largely relied on Json.NET and other popular JSON libraries, which continue to be good choices. Json.NET 使用 .NET 字符串作为其基本数据类型,它实际上是 UTF-16。Json.NET uses .NET strings as its base datatype, which is UTF-16 under the hood.

新的内置 JSON 支持具有高性能、低分配的特点,并基于 Span<byte>The new built-in JSON support is high-performance, low allocation, and based on Span<byte>. 有关 System.Text.Json 命名空间和类型的详细信息,请参阅 .NET 中的 JSON 序列化 - 概述For more information about the System.Text.Json namespace and types, see JSON serialization in .NET - overview. 有关常见 JSON 序列化方案的教程,请参阅如何在 .NET 中序列化和反序列化 JSONFor tutorials on common JSON serialization scenarios, see How to serialize and deserialize JSON in .NET.

HTTP/2 支持HTTP/2 support

System.Net.Http.HttpClient 类型支持 HTTP/2 协议。The System.Net.Http.HttpClient type supports the HTTP/2 protocol. 如果启用 HTTP/2,则将通过 TLS/ALPN 协商 HTTP 协议版本,并在服务器选择使用 HTTP/2 时使用。If HTTP/2 is enabled, the HTTP protocol version is negotiated via TLS/ALPN, and HTTP/2 is used if the server elects to use it.

默认协议将保留 HTTP/1.1,但可以在两种不同方法中启用 HTTP/2。The default protocol remains HTTP/1.1, but HTTP/2 can be enabled in two different ways. 首先,可以将 HTTP 请求消息设置为使用 HTTP/2:First, you can set the HTTP request message to use HTTP/2:

var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };

// HTTP/1.1 request
using (var response = await client.GetAsync("/"))
    Console.WriteLine(response.Content);

// HTTP/2 request
using (var request = new HttpRequestMessage(HttpMethod.Get, "/") { Version = new Version(2, 0) })
using (var response = await client.SendAsync(request))
    Console.WriteLine(response.Content);

其次,可以更改 HttpClient 以默认使用 HTTP/2:Second, you can change HttpClient to use HTTP/2 by default:

var client = new HttpClient()
{
    BaseAddress = new Uri("https://localhost:5001"),
    DefaultRequestVersion = new Version(2, 0)
};

// HTTP/2 is default
using (var response = await client.GetAsync("/"))
    Console.WriteLine(response.Content);

很多时候,在你开发应用程序时要使用未加密的连接。Many times when you're developing an application, you want to use an unencrypted connection. 如果你知道目标终结点将使用 HTTP/2,你可以为 HTTP/2 打开未加密的连接。If you know the target endpoint will be using HTTP/2, you can turn on unencrypted connections for HTTP/2. 可以通过将 DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT 环境变量设置为 1 或通过在应用上下文中启用它来将其打开:You can turn it on by setting the DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT environment variable to 1 or by enabling it in the app context:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

后续步骤Next steps