Announcing .NET 5.0/发布


We’re excited to release .NET 5.0 today and for you to start using it. It’s a major release — including C# 9 and F# 5 — with a broad set of new features and compelling improvements. It’s already in active use by teams at Microsoft and other companies, in production and for performance testing. Those teams are showing us great results that demonstrate performance gains and/or opportunities to reduce hosting costs for their web applications. We’ve been running our own website on 5.0 since Preview 1. From what we’ve seen and heard so far, .NET 5.0 delivers significant value without much effort to upgrade. It’s a great choice for your next app, and a straightforward upgrade from earlier .NET Core versions. We hope you enjoy using it, on your desktop, laptop, and cloud instances.


ASP.NET Core, EF Core, C# 9, and F# 5 are also being released today. .NET Conf 2020 — our free and virtual conference — is being held today so you can learn about all of the new releases.

You can download .NET 5.0, for Windows, macOS, and Linux, for x86, x64, Arm32, Arm64.

ASP.NETCore、EF Core、C#9和F#5也将于今天发布。今天我们的虚拟会议是免费的,你可以了解我们的所有会议。


Installers and binaries

Container images

Linux packages

Release notes

Known issues

GitHub issue tracker

.NET 5.0 Contributors

For Visual Studio users, you need Visual Studio 16.8 or later to use .NET 5.0 on Windows and the latest version of Visual Studio for Mac) on macOS. The C# extension for Visual Studio Code already supports .NET 5.0 and C# 9.

对于Visual Studio用户,需要Visual Studio 16.8或更高版本才能在Windows上使用.NET 5.0,在Mac OS上使用最新版本的Visual Studio For Mac)。Visual Studio代码的C扩展已支持.NET 5.0和C#9。

.NET 5.0 is the first release in our .NET unification journey. We built .NET 5.0 to enable a much larger group of developers to migrate their .NET Framework code and apps to .NET 5.0. We’ve also done much of the early work in 5.0 so that Xamarin developers can use the unified .NET platform when we release .NET 6.0. There is more on .NET unification, later in the post.


Now is a good time to call out the incredible collaboration with everyone contributing to the .NET project. This release marks the fifth major .NET version as an open source project. There is now a large mix of individuals and small and large companies (including the .NET Foundation corporate sponsors) working together as a large community on various aspects of .NET in the dotnet org on GitHub. The improvements in .NET 5.0 are the result of many people, their effort, smart ideas, and their care and love for the platform, all above and beyond Microsoft’s stewardship of the project. From the core team working on .NET every day, we extend a very large “thank you” to everyone that contributed to .NET 5.0 (and previous releases)!


We introduced .NET 5.0 way back in May 2019, and even set the November 2020 release date at that time. From that post: “we will ship .NET Core 3.0 this September, .NET 5 in November 2020, and then we intend to ship a major version of .NET once a year, every November”. You’d think that “November 2020” was a cheque that could not be cashed given all the challenges this year, however, .NET 5.0 has been released on time. Thanks to everyone on the team that made that happen! I know it has not been easy. Looking forward, you should expect .NET 6.0 in November 2021. We intend to release new .NET versions every November.


The rest of the blog is dedicated to highlighting and detailing most of the improvements in .NET 5.0. There is also an update on our .NET unification vision.


.NET 5.0 Highlights/.NET 5.0亮点
There are many important improvements in .NET 5.0:

.NET 5.0中有许多重要的改进:

.NET 5.0 is already battle-tested by being hosted for months at and (version).

Performance is greatly improved across many components and is described in detail at Performance Improvements in .NET 5.0, Arm64 Performance in .NET 5.0, and gRPC.

C# 9 and F# 5 offer new language improvements such as top-level programs and records for C# 9, while F# 5 offers interactive programming and a performance boost for functional programming on .NET.

.NET libraries have enhanced performance for Json serialization, regular expressions, and HTTP (HTTP 1.1, HTTP/2). They are also are now completely annotated for nullability.

P95 latency has dropped due to refinements in the GC, tiered compilation, and other areas.

Application deployment options are better, with ClickOnce client app publishing, single-file apps, reduced container image size, and the addition of Server Core container images.

Platform scope expanded with Windows Arm64 and WebAssembly.




.NET库增强了Json序列化、正则表达式和HTTP(HTTP 1.1、HTTP/2)的性能。它们现在也完全被注释为空。



使用Windows Arm64和WebAssembly扩展了平台范围。

I’ve written many samples for the .NET 5.0 preview posts. You might want to take a look at .NET 5.0 Examples to learn more about new C# 9 and libraries features.


Platform and Microsoft Support/平台和Microsoft支持
.NET 5.0 has a nearly identical platform support matrix as .NET Core 3.1, for Windows, macOS, and Linux. If you are using .NET Core 3.1 on a supported operating system, you should be able to adopt .NET 5.0 on that same operating system version for the most part. The most significant addition for .NET 5.0 is Windows Arm64.


.NET 5.0 is a current release. That means that it will be supported for three months after .NET 6.0 is released. As a result, we expect to support .NET 5.0 through the middle of February 2022. .NET 6.0 will be an LTS release and will be supported for three years, just like .NET Core 3.1.


Unified platform vision/统一平台愿景
Last year, we shared a vision of a unified .NET stack and ecosystem. The value to you is that you will be able to use a single set of APIs, languages, and tools to target a broad set of application types, including mobile, cloud, desktop, and IoT. You might realize that you can already target a broad set of platforms with .NET today, however, the tools and APIs are not always the same across Web and Mobile, for example, or released at the same time.


As part of .NET 5.0 and 6.0, we are unifying .NET into a single product experience, while enabling you to pick just the parts of the .NET platform that you want to use. If you want to target Mobile and not WebAssembly, you don’t need to download the WebAssembly tools, and vice versa. Same with ASP.NET Core and WPF. You’ll also have a much easier way to acquire all the .NET tools and build and runtime packs that you need from the command line. We’re enabling a package manager experience (including using existing package managers) for .NET platform components. That will be great for many scenarios. Quick construction of a development environment and CI/CD will probably be the biggest beneficiaries.

作为.NET 5.0和6.0的一部分,我们将.NET统一到一个单一的产品体验中,同时使您能够选择您想要使用的.NET平台的各个部分。如果您希望以移动而不是WebAssembly为目标,则不需要下载WebAssembly工具,反之亦然。与…相同ASP.NET核心和WPF。您还可以更轻松地从命令行获取所需的所有.NET工具、构建包和运行时包。我们正在为.NET平台组件启用包管理器体验(包括使用现有的包管理器)。这对很多场景都很好。快速构建发展环境和CI/CD可能是最大的受益者。

We had intended to deliver the entirety of the unification vision with .NET 5.0, but in the wake of the global pandemic, we had to adapt to the changing needs of our customers. We’ve been working with teams from companies from around the world that have needed help to speed up their adoption of cloud technologies. They, too, have had adapt to the changing needs of their customers. As a result, we are delivering the vision across two releases.


The first step towards this vision was consolidating .NET repos, including a large subset of Mono. Having one repo for the runtime and libraries for .NET is a precondition to delivering the same product everywhere. It also helps with making broad changes that affect runtime and libraries, where there were previously repo boundaries. Some people were worried that a large repo would be harder to manage. That hasn’t proven to be the case.


In the .NET 5.0 release, Blazor is best example of taking advantage of repo consolidation and .NET unification. The runtime and libraries for Blazor WebAssembly are now built from the consolidated dotnet/runtime repo. That means Blazor WebAssembly and Blazor on the server use the exact same code for List, for example. That wasn’t the case for Blazor prior to .NET 5.0. The approach we took for Blazor WebAssembly is very similar to what we’ll do with Xamarin in .NET 6.0.

在.NET5.0版本中,Blazor是利用回购合并和.NET统一的最佳示例。Blazor WebAssembly的运行时和库现在是从合并的dotnet/runtime repo构建的。这意味着服务器上的Blazor WebAssembly和Blazor对List使用完全相同的代码。对于.NET5.0之前的Blazor,情况并非如此。我们对BlazorWebAssembly采取的方法与我们在.NET6.0中对Xamarin的处理非常相似。

The .NET Framework remains a supported Microsoft product and will continue to be supported with each new version of Windows. We announced last year that we had stopped adding new features to .NET

.NET Framework仍然是受支持的Microsoft产品,并且将继续受Windows的每个新版本的支持。我们去年宣布停止向.NET添加新功能

Framework and finished adding .NET Framework APIs to .NET Core. That means that now is a great time to consider moving your .NET Framework apps to .NET Core. For .NET Framework client developers, Windows Forms and WPF are supported with .NET 5.0. We’ve heard from many developers that porting from .NET Framework is straightforward. For .NET Framework server developers, you need to adopt ASP.NET Core to use .NET 5.0. For Web Forms developers, we believe that Blazor provides a similar developer experience with an efficient and much more modern implementation. WCF server and Workflow users can look to community projects that are supporting those frameworks. The porting from .NET Framework to .NET Core doc is a good place to start. That all said, keeping your app on .NET Framework is a fine approach if you are happy with your experience.

已完成向.NET核心添加.NET Framework API。这意味着现在是考虑将.NET Framework应用程序迁移到.NET核心的好时机。对于.NETFramework客户端开发人员,.NET5.0支持Windows窗体和WPF。我们从许多开发人员那里听说从.NETFramework移植是很简单的。对于.NETFramework服务器开发人员,您需要采用ASP.NET使用.NET5.0的核心。对于Web表单开发人员,我们相信Blazor提供了类似的开发人员体验,具有高效和更现代的实现。wcfserver和工作流用户可以查看支持这些框架的社区项目。从.NETFramework移植到.NET核心文档是一个很好的开始。总之,如果你对自己的体验感到满意,将你的应用程序保留在.NETFramework上是一个很好的方法。

The Windows team is working on Project Reunion as the next step forward for UWP and related technologies. We’ve been collaborating with the Reunion team to ensure that .NET 5.0 and later versions will work well with WinUI and WebView2. The Project Reunion repo is the best place to stay up to date with progress.


Let’s switch to looking at what’s new in the 5.0 release.


C# 9 and F# 5 are part of the .NET 5.0 release and included in the .NET 5.0 SDK. Visual Basic is also included in the 5.0 SDK. It does not include language changes, but has improvements to support the Visual Basic Application Framework on .NET Core.


C# Source Generators are an important new C# compiler feature. They are not technically part of C# 9 since it doesn’t have any language syntax. See New C# Source Generator Samples to help you get started using this new feature. We expect to make more use of source generators within the .NET product in .NET 6.0 and beyond.


As a way to try out the new release ourselves, a few of us decided to update the dotnet/iot repo to use new C# 9 syntax and target .NET 5.0. The changes resulted in removing >2k lines of code, just by adopting new syntax. It uses top-level programs, records, patterns, and switch expressions. It has also been updated to take advantage of the complete set of nullable annotations in .NET libraries. We also updated the .NET IoT docs. We’ll take a look at few examples from that repo to explore C# 9.

作为自己尝试新版本的一种方式,我们中的一些人决定更新dotnet/iot repo以使用新的C#9语法和目标.net5.0。这些更改只需采用新的语法,就可以删除超过2k行的代码。它使用顶级程序、记录、模式和开关表达式。它还进行了更新,以利用.NET库中可为null的完整注释集。我们还更新了.NET IoT文档。我们将从该回购协议中查看几个示例来探索C#9。

Top-level programs/顶级课程
The led-blink program is a nice compact top-level program example.


using System;using System.Device.Gpio;using System.Threading;var pin = 18;var lightTime = 1000;var dimTime = 200;Console.WriteLine( " L e t ′ s b l i n k a n L E D ! " ) ; u s i n g G p i o C o n t r o l l e r c o n t r o l l e r = n e w ( ) ; c o n t r o l l e r . O p e n P i n ( p i n , P i n M o d e . O u t p u t ) ; C o n s o l e . W r i t e L i n e ( "Let's blink an LED!");using GpioController controller = new (); controller.OpenPin(pin, PinMode.Output);Console.WriteLine( "LetsblinkanLED!");usingGpioControllercontroller=new();controller.OpenPin(pin,PinMode.Output);Console.WriteLine(“GPIO pin enabled for use: {pin}”);// turn LED on and offwhile (true){
Console.WriteLine($“Light for {lightTime}ms”);
controller.Write(pin, PinValue.High);

Console.WriteLine($"Dim for {dimTime}ms");
controller.Write(pin, PinValue.Low);

You can also see the use of target-typed new, with the assignment to the controller variable. The GpioController type is only defined on the left-hand side of the assignment. The type is inferred on the right-hand side. This new syntax is an alternative to var, which has the type only showing on the right-hand side of the assignment and is inferred on the left-hand side with the var keyword.


Top-level programs can also grow in complexity, by defining methods and taking advantage of types defined in the same or other files. The CharacterLcd sample demonstrates some of those capabilities.


Logical and property patterns/逻辑和属性模式
C# 9 includes support for new patterns. You can see an example of a logical pattern in the following code from the CCS811 Gas sensor.


var threshChoice = Console.ReadKey();Console.WriteLine();if (threshChoice.KeyChar is ‘Y’ or ‘y’){
Another new pattern is property patterns. You can see several properties checks in my Mycroft information access 6.0 sample. The following code is taken from the PN532 RFID and NFC reader sample.


if (pollingType is null or { Length: >15 }){
return null;}
This code tests if pollingType (which is typed as byte[]?) is null or contains >15 bytes.


I want to show you two more patterns. The first is a logical pattern in Mcp25xxx CAN bus.

我想再给你看两种模式。第一种是Mcp25xxx CAN总线中的逻辑模式。

public static byte GetRxBufferNumber(Address address) => address switch{
>= Address.RxB0D0 and <= Address.RxB0D7 => 0,
>= Address.RxB1D0 and <= Address.RxB1D7 => 1,
_ => throw new ArgumentException(nameof(address), $“Invalid address value {address}.”),};
The second is a logical pattern in Piezo Buzzer Controller.


if (element is not NoteElement noteElement){
// In case it’s a pause element we have only just wait desired time.
// In case it’s a note element we play it.
var frequency = GetFrequency(noteElement.Note, noteElement.Octave);
_buzzer.PlayTone(frequency, (int)(durationInMilliseconds * 0.7));
Thread.Sleep((int)(durationInMilliseconds * 0.3));}
C# 9 includes a new type of class called a record. It has a number of benefits compared to regular classes, half of which relate to more terse syntax. The following record is taken from the Bh1745 RGB Sensor binding.

C#9包含一种新的类,称为记录。与常规类相比,它有许多优点,其中一半与更简洁的语法有关。以下记录取自Bh1745 RGB传感器绑定。

public record ChannelCompensationMultipliers(double Red, double Green, double Blue, double Clear);
It is then used a little later in the same file, with familiar syntax:


ChannelCompensationMultipliers = new (2.2, 1.0, 1.8, 10.0);
Nullability annotation improvements/可空性注释改进
The .NET libraries are now completely annotated for nullability. That means if you enable nullability, you’ll get more type information from the platform to direct your use of the feature. At present, the .NET docs have not been fully annotated. For example, String.IsNullOrEmpty(string) should be annotated to take a string?, while String.Split(Char[]) has an annotation of char[]?. We hope that will get fixed soon. Complete information is available at and via F12 metadata lookups in Visual Studio.

NET库现在已经完全注释为空。这意味着,如果您启用了nullability,您将从平台获得更多类型信息,以指导您使用该特性。目前,.NET文档尚未完全注释。例如,String.IsNullOrEmpty(string)应该加注释以获取字符串?,同时字符串。拆分(Char[])的注释为Char[]?。我们希望很快就能修好。完整信息请访问源.dot.net通过Visual Studio F12查找元数据。

The System.Device.Gpio and Iot.Device.Bindings packages (version 1.1.0 for both) have also been annotated as part of this release, using the updated .NET 5.0 annotations. Those libraries are both multi-targeted, however, we use the 5.0 view to produce annotations for all targets.


Note: Existing .NET Core 3.1 code might generate new diagnostics (if you have nullability enabled) when you retarget it to .NET 5.0, since there are new annotations.


We’ve also added new annotation types. It’s common for large classes to instantiate object members in helper methods called from a constructor. The C# compiler can’t follow the flow of calls to the object assignment. It will think that the member is null when exiting the constructor and will warn with CS8618. The MemberNotNull attribute resolves this problem. You apply the attribute to the helper method. The compiler will then see that you set this value and realize that the method is called from a constructor. MemberNotNullWhen is similar.


You can see an example of MemberNotNull in the BMxx80 temperature sensors with the following code.


[MemberNotNull(nameof(_calibrationData))]private void ReadCalibrationData(){
switch (this)
case Bme280 _:
_calibrationData = new Bme280CalibrationData();
_controlRegister = (byte)Bmx280Register.CTRL_MEAS;
case Bmp280 _:
_calibrationData = new Bmp280CalibrationData();
_controlRegister = (byte)Bmx280Register.CTRL_MEAS;
case Bme680 _:
_calibrationData = new Bme680CalibrationData();
_controlRegister = (byte)Bme680Register.CTRL_MEAS;
throw new Exception(“Bmxx80 device not correctly configured. Could not find calibraton data.”);

The actual code uses conditional compilation. That’s because the project is multi-targeted, and this attribute is only supported with .NET 5.0+ . The use of the attribute enables skipping runtime checks (in the constructor) that would otherwise be needed to satisfy nullability requirements, as is the case for earlier .NET versions.


We’ve improved the Windows Forms designer, changed the way that target frameworks work for .NET 5.0 and beyond, changed the way that WinRT is supported, and made other improvements.


Windows Forms designer/Windows窗体设计器
The Windows Forms designer (for .NET Core 3.1 and .NET 5.0) has been updated in Visual Studio 16.8, and now supports all Windows Forms controls. It also supports the Telerik UI for WinForms controls. The designer includes all the designer functionality you would expect, including: drag-and-drop, selection, move and resize, cut/copy/paste/delete of controls, integration with the Properties Window, events generation and more. Data binding and support for a broader set of third party controls is coming soon.

Windows窗体设计器(用于.NET Core 3.1和.NET 5.0)已在Visual Studio 16.8中更新,现在支持所有Windows窗体控件。它还支持WinForms控件的Telerik用户界面。设计器包含您所期望的所有设计器功能,包括:拖放、选择、移动和调整大小、剪切/复制/粘贴/删除控件、与属性窗口集成、事件生成等。数据绑定和对更广泛的第三方控制的支持即将到来。

Learn more in the Windows Forms Designer for .NET Core Released post.

有关详细信息,请参阅Windows窗体设计器for.NET Core发布的文章。

.NET 5.0 Target Framework/.NET 5.0目标框架
We have changed the approach we use for target frameworks with .NET 5.0. The following project file demonstrate the new .NET 5.0 target framework.


Exe net5.0 The new net5.0 form is more compact and intuitive than the netcoreapp3.1 style we’ve used until this point. In addition, we are extending the target framework to describe operating system dependencies. This change is motivated by our vision to enable targeting iOS and Android with Xamarin in .NET 6.0.


Windows desktop APIs (including Windows Forms, WPF, and WinRT) will only be available when targeting net5.0-windows. You can specify an operating system version, like net5.0-windows7 or net5.0-windows10.0.17763.0 ( for Windows October 2018 Update). You need to target a Windows 10 version if you want to use WinRT APIs.

Windows桌面API(包括Windows窗体、WPF和WinRT)仅在针对net5.0-Windows时可用。您可以指定操作系统版本,如net5.0-windows7或net5.0-windows10.0.17763.0(对于Windows 2018年10月更新)。如果您需要使用WinRT API版本,则需要使用WinRT API。

Cross-platform scenarios can be a bit more challenging, when using the new net5.0-windows TFM. System.Device.Gpio demonstrates a pattern for managing the Windows target-framework if you want to avoid building for Windows or avoid pulling Windows runtime packages on Linux, for example.

当使用新的net5.0-windows TFM时,跨平台场景可能会更具挑战性。系统设备.Gpio举例来说,如果您希望避免为Windows构建或避免在Linux上拉取Windows运行时包,则演示一种管理Windows目标框架的模式。

Summary of changes:

net5.0 is the new Target Framework Moniker (TFM) for .NET 5.0.

net5.0 combines and replaces netcoreapp and netstandard TFMs.

net5.0 supports .NET Framework compatibility mode

net5.0-windows will be used to expose Windows-specific functionality, including Windows Forms, WPF and WinRT APIs.

.NET 6.0 will use the same approach, with net6.0, and will add net6.0-ios and net6.0-android.

The OS-specific TFMs can include OS version numbers, like net6.0-ios14.

Portable APIs, like ASP.NET Core will be usable with net5.0. The same will be true of Xamarin forms with net6.0.



net5.0结合并取代了netcoreapp和netstandard TFMs。

net5.0支持.NET Framework兼容模式





The templates in Visual Studio 16.8 still target .NET Core 3.1, for console, WPF and Windows Forms apps. The ASP.NET templates have been updated to support .NET 5.0. We will update the templates in Visual Studio 16.9 for the remaining templates.


WinRT Interop (Breaking Change)/WinRT Interop(中断更改)
On the topic of targeting Windows APIs, we have moved to a new model for supporting WinRT APIs as part of .NET 5.0. This includes calling APIs (in either direction; CLR <==> WinRT), marshaling of data between the two type systems, and unification of types that are intended to be treated the same across the type system or ABI boundary (i.e. “projected types”; IEnumerable and IIterable are examples).

关于面向WindowsAPI的主题,我们已经转向了一种新的模型,它支持WinRT API作为.NET5.0的一部分。这包括调用api(在任何方向;CLR<=>WinRT),在两个类型系统之间封送数据,以及在类型系统或ABI边界上统一处理相同的类型(即“投影类型”;IEnumerable和IIterable都是示例)。

The existing WinRT interop system has been removed from the .NET runtime as part of .NET 5.0. This is a breaking change. That means that apps and libraries using WinRT with .NET Core 3.x will need to be rebuilt and will not run on .NET 5.0 as-is. Libraries that use WinRT APIs will need to multi-target to manage this difference between .NET Core 3.1 and .NET 5.0.

现有的WinRT互操作系统已作为.NET 5.0的一部分从.NET运行时中删除。这是一个突破性的变化。这意味着需要重新构建使用WinRT和.NETCore3.x的应用程序和库,而不能像现在这样在.NET5.0上运行。使用WinRT API的库需要多目标来管理.NETCore3.1和.NET5.0之间的差异。

Going forward, we will rely on the new CsWinRT tool provided by the WinRT team in Windows. It generates C#-based WinRT interop assemblies, which can be delivered via NuGet. That’s exactly what the Windows team is doing, for the WinRT APIs in Windows. The tool can be used by anyone that wants to use WinRT (on Windows) as an interop system, to expose native APIs to .NET or .NET APIs to native code.


The CsWinRT tool is logically similar to tlbimp and tlbexp, although much better. The tlb tools relied on a lot of COM interop plumbing in the .NET runtime. The CsWinRT tool only relies on public .NET APIs. That said, the function pointers feature in C# 9 — and partially implemented in the .NET 5.0 runtime — was in part inspired by the needs of the CsWinRT tool.


There are several benefits to this new WinRT interop model:

It can be developed and improved separate from the .NET runtime.

It is symmetrical with the tool-based interop systems provided for other OSes, like iOS and Android.

The tool can take advantage of other .NET features (AOT, C# features, IL linking), which was not an option for the previous system.

Simplifies the .NET runtime codebase.






You don’t need to add NuGet references to use WinRT APIs. Targeting a Windows 10 TFM — just discussed in the .NET 5.0 TFM section earlier — is enough. If you target .NET Core 3.1 or earlier, you need to reference WinRT packages. You can see this pattern in the System.Device.Gpio project.

不需要添加NuGet引用就可以使用winrtapi。以Windows10TFM为目标—刚才在.NET5.0TFM一节中讨论过—就足够了。如果目标是.NET Core 3.1或更早版本,则需要引用WinRT包。你可以在系统设备.Gpio项目。

Native exports/本地出口
We’ve had requests to enable exports for native binaries that calls into .NET code for a long time. The building block for the scenario is hosting API support for UnmanagedCallersOnlyAttribute.


This feature is a building-block for creating higher level experiences. Aaron Robinson, on our team, has been working on a .NET Native Exports project that provides a more complete experience for publishing .NET components as native libraries. We’re looking for feedback on this capability to help decide if the approach should be included in the product.

此功能是创建更高级别体验的构建块。Aaron Robinson在我们的团队中一直致力于一个.NET本机导出项目,该项目为将.NET组件作为本机库发布提供了更完整的体验。我们正在寻找关于此功能的反馈,以帮助决定该方法是否应包含在产品中。

The .NET Native exports project enables you to:

Expose custom native exports.

Doesn’t require a higher-level interop technology like COM.

Works cross-platform.

.NET Native exports项目使您能够:




There are existing projects that enable similar scenarios, such as:

Unmanaged Exports





Over the years, we’ve seen a variety of hosting models for .NET in native applications. @rseanhall proposed and implemented a novel new model for doing that, which takes advantage of all the built-in application functionality offered by the .NET application hosting layer (specifically loading dependencies), while enabling a custom entrypoint to be called from native code. That’s perfect for a lot of scenarios, and that one can imagine becoming popular with developers that host .NET components from native applications. That didn’t exist before. Thanks for the contribution, @rseanhall.


Two primary PRs:

Enable calling get_runtime_delegate from app context

Implement hdt_get_function_pointer




Event pipe/事件管道
Event pipe is a new subsystem and API that we added in .NET Core 2.2 to make it possible to perform performance and other diagnostic investigations on any operating system. In .NET 5.0, the event pipe has been extended to enable profilers to write event pipe events. This scenario is critical for instrumenting profilers that previously relied on ETW (on Windows) to monitor application behavior and performance.


Assembly load information is now available via event pipe. This improvement is the start of making similar diagnostics functionality available as is part of .NET Framework, such as the Fusion Log Viewer. You can now use dotnet-trace to collect this information, using the following command:

现在可以通过事件管道获得程序集加载信息。这一改进是使类似的诊断功能可用的开始,它是.NET框架的一部分,如Fusion Log Viewer。现在可以使用以下命令使用dotnet trace收集此信息:

dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4:4 – ./MyApp –my-arg 1
The workflow is described in the dotnet-trace docs. You can see assembly loading information for a simple test app.


We’ve made improvements to the console log provider in the Microsoft.Extensions.Logging library. You can now implement a custom ConsoleFormatter to exercise complete control over formatting and colorization of the console output. The formatter APIs allow for rich formatting by implementing a subset of the VT-100 (supported by most modern terminals) escape sequences. The console logger can parse out escape sequences on unsupported terminals allowing you to author a single formatter for all terminals.


In addition to support for custom formatters, we’ve also added a built-in JSON formatter that emits structured JSON logs to the console.


Dump debugging/转储调试
Debugging managed code requires knowledge of managed objects and constructs. The Data Access Component (DAC) is a subset of the runtime execution engine that has knowledge of these constructs and can access these managed objects without a runtime. .NET Core process dumps collected on Linux can now be analyzed on Windows using WinDBG or dotnet dump analyze.

调试托管代码需要了解托管对象和构造。数据访问组件(DAC)是运行时执行引擎的一个子集,它了解这些构造,并且可以在不使用运行时的情况下访问这些托管对象。现在可以在Windows上使用WinDBG或dotnet dump analyze分析在Linux上收集的NET核心进程转储。

We’ve also added support for capturing ELF dumps from .NET processes running on macOS. Since ELF is not the native executable (native debuggers like lldb will not work with these dumps) file format on macOS, we have made this an opt-in feature. To enable support for dump collection on macOS, set the environment variable COMPlus_DbgEnableElfDumpOnMacOS=1. The resulting dumps can be analyzed using dotnet dump analyze.

我们还添加了对从运行在macOS上的.NET进程捕获ELF转储的支持。由于ELF不是macOS上的本机可执行文件格式(像lldb这样的本机调试器无法处理这些转储文件),所以我们将其作为一种选择加入特性。要在macOS上启用对转储收集的支持,请设置环境变量COMPlus_dbgenablelfdumponmacos=1。可以使用dotnet dump analyze分析结果转储。

Printing environment information/打印环境信息
As .NET has extended support for new operating systems and chip architectures, people sometimes want a way to print environment information. We created a simple .NET tool that does this, called dotnet-runtimeinfo.


You can install and run the tool with the following commands.


dotnet tool install -g dotnet-runtimeinfo
The tool produces output in the following form for your environment.


**.NET information
Version: 5.0.0FrameworkDescription: .NET 5.0.0Libraries version: 5.0.0Libraries hash: cf258a14b70ad9069470a108f13765e0e5988f51

Environment information
OSDescription: Linux 5.8.6-1-MANJARO-ARM #1 SMP Thu Sep 3 22:01:08 CEST 2020OSVersion: Unix Arm64ProcessorCount: 6
CGroup info**
cfs_quota_us: -1
memory.limit_in_bytes: 9223372036854771712
memory.usage_in_bytes: 2740666368
Runtime and Libraries/运行时和库
There were many improvements across the runtime and libraries.


Code quality improvements in RyuJIT/RyuJIT的代码质量改进
There were a lot of improvements to the JIT this release, many of which I shared in previous .NET 5.0 preview posts. In this post, I’m elevating the changes that came from the community.


Use xmm for stack prolog – dotnet/runtime #32538 — Change to x86/x64 prolog zeroing code. Improvements: Json; TechEmpower. Credit: Ben Adams.

Vectorise BitArray for Arm64 – dotnet/runtime #33749 — The BitArray class was updated to include a hardware-accelerated implementation for Arm64 using Arm64 intrinisics. The performance improvements for BitArray are very significant. Credit to @Gnbrkm41.

Dynamic generic dictionary expansion feature dotnet/runtime #32270 – Some (maybe most?) uses of generics now have better performance (initial performance findings), based on improving the implementation of low-level (native code) dictionaries used by the runtime to store information about generic types and methods. See Perf: Collection Count() is Slower in Core than the CLR for more information. Credit to @RealDotNetDave for the bug report.

Implement Vector.Ceiling / Vector.Floor dotnet/runtime #31993 – Implement Vector.Ceiling / Vector.Floor using x64 and Arm64 intrinsics, per API proposal. Credit to @Gnbrkm41.

New, much faster, portable implementation of tailcall helpers. Credit: Jakob Botsch Nielsen (.NET team intern). Reaction from @dsymetweets.

Add VectorTableList and TableVectorExtension intrinsics — Credit: @TamarChristinaArm (ARM Holdings)

Improved Intel architecture performance using new hardware intrinsics BSF/BSR — Credit @saucecontrol

Implement Vector{Size}.AllBitsSet — Credit @Gnbrkm41

Enable eliding some bounds checks — Credit @nathan-moore

将xmm用于堆栈prolog–dotnet/runtime#32538-更改为x86/x64 prolog零位代码。改进:Json;TechEmpower。作者:本·亚当斯。

Arm64的Vectorise BitArray–dotnet/runtime#33749-BitArray类已更新,以包含使用Arm64 Intrinsics的硬件加速的Arm64实现。BitArray的性能改进非常显著。记入@Gnbrkm41。

动态通用字典扩展功能dotnet/runtimeŠ32270–一些(可能是大多数?)基于改进运行时用于存储泛型类型和方法信息的低级(本机代码)字典的实现,泛型的使用现在有了更好的性能(初始性能发现)。有关详细信息,请参阅Perf:Collection Count()在核心中比CLR慢。缺陷报告归功于@RealDotNetDave。

实施矢量天花板/ 矢量地板dotnet/runtime#31993–实现矢量天花板/ 矢量地板根据API建议使用x64和Arm64内部函数。记入@Gnbrkm41。

新的,更快的,可移植的tailcall助手的实现。作者:Jakob Botsch Nielsen(.NET团队实习生)。@dsymetweets的反应。

添加VectorTableList和tablevectorenextension intrinsics-Credit:@TamarChristinaArm(ARM控股公司)



允许省略一些边界检查-信贷@nathan moore

Garbage Collector/垃圾收集器
The following improvements were made in the GC.

Card mark stealing – dotnet/coreclr #25986 — Server GC (on different threads) can now work-steal while marking gen0/1 objects held live by older generation objects. This means that ephemeral GC pauses are shorter for scenarios where some GC threads took much longer to mark than others.

Introducing Pinned Object Heap – dotnet/runtime #32283 — Adds the Pinned Object Heap (POH). This new heap (a peer to the Large Object Heap (LOH)) will allow the GC to manage pinned objects separately, and as a result avoid the negative effects of pinned objects on the generational heaps.

Allow allocating large object from free list while background sweeping SOH — Enabled LOH allocations using the free list while BGC is sweeping SOH. Previously this was only using end of segment space on LOH. This allowed for better heap usage.

Background GC suspension fixes – dotnet/coreclr #27729 — Suspension fixes to reduce time for both BGC and user threads to be suspended. This reduces the total time it takes to suspend managed threads before a GC can happen. dotnet/coreclr #27578 also contributes to the same outcome.

Fix named cgroup handling in docker — Added support to read limits from named cgroups. Previously we only read from the global one.

Optimize vectorized sorting – dotnet/runtime #37159 — vectorized mark list sorting in GC which reduces the ephemeral GC pause time (also dotnet/runtime #40613).

Generational aware analysis – dotnet/runtime #40322 — generational aware analysis that allows you to determine what old generation objects hold on to younger generation objects thus making them survive and contribute to ephemeral GC pause time.

Optimize decommitting GC heap memory pages – dotnet/runtime #35896 — optimized decommit, much better decommit logic and for Server GC took decommit completely out of the “stop the world” phase which reduced blocking GC pause time.





后台GC暂停修复-dotnet/corecrr#27729-暂停修复,以减少BGC和用户线程暂停的时间。这减少了在GC发生之前挂起托管线程所需的总时间。dotnet/corecrr 27578也有助于获得同样的结果。





The GC now exposes detailed information of the most recent collection, via the GC.GetGCMemoryInfo method. The GCMemoryInfo struct provides information about machine memory, heap memory and the most recent collection, or most recent collection of the kind of GC you specify – ephemeral, full blocking or background GC.


The most likely use cases for using this new API are for logging/monitoring or to indicate to a loader balancer that a machine should be taken out of rotation to request a full GC. It could also be used to avoid container hard-limits by reducing the size of caches.


Another, small but impactful change, was made to defer the expensive reset memory operation to low-memory situations. We expect these changes in policy to lower the GC latency (and GC CPU usage in general).

另一个小的但有影响的改变是将昂贵的重置内存操作推迟到内存不足的情况。我们期望这些策略上的更改能够降低GC延迟(以及GC CPU的一般使用率)。

Windows Arm64
.NET apps can now run natively on Windows Arm64. This follows the support we added for Linux Arm64 (support for glibc and musl) with .NET Core 3.0. With .NET 5.0, you can develop and run apps on Windows Arm64 devices, such as Surface Pro X. You can already run .NET Core and .NET Framework apps on Windows Arm64, but via x86 emulation. It’s workable, but native Arm64 execution has much better performance.

.NET应用程序现在可以在Windows Arm64上以本机方式运行。这是我们为LinuxARM64(支持glibc和musl)添加的.NETCore3.0支持。使用.NET 5.0,您可以在Windows Arm64设备(如Surface Pro X)上开发和运行应用程序。您已经可以在Windows Arm64上运行.NET Core和.NET Framework应用程序,但要通过x86仿真。它是可行的,但是本机Arm64执行有更好的性能。

MSI installers for Arm64 were one of the final changes this release. You can see the .NET 5.0 SDK installer in the following image.


The .NET 5.0 SDK does not currently contain the Windows Desktop components — Windows Forms and WPF — on Windows Arm64. This change was initially shared in the .NET 5.0 Preview 8 post. We are hoping to add the Windows desktop pack for Windows Arm64 in a 5.0 servicing update. We don’t currently have a date to share. Until then, the SDK, console and ASP.NET Core applications are supported on Windows Arm64, but not Windows Desktop components.

.NET5.0SDK当前不包含WindowsARM64上的Windows桌面组件—WindowsForms和WPF。这个变化最初是在.NET5.0预览版8中共享的。我们希望在5.0服务更新中添加windowsrm64的Windows桌面包。我们目前没有要分享的日期。在此之前,SDK、控制台和ASP.NETWindows Arm64支持核心应用程序,但不支持Windows桌面组件。

Arm64 Performance/Arm64性能
We’ve been investing significantly in improving Arm64 performance, for over a year. We’re committed to making Arm64 a high-performance platform with .NET. These improvements apply equally to Windows and Linux. Platform portability and consistency have always been compelling characteristics of .NET. This includes offering great performance wherever you use .NET. With .NET Core 3.x, Arm64 has functionality parity with x64 but is missing some key performance features and investments. We’ve resolved that in .NET 5.0, as described in Arm64 Performance in .NET 5.0.


The improvements:

Tune JIT optimizations for Arm64 (example)

Enable and take advantage of Arm64 hardware intrinsics (example).

Adjust performance-critical algorithms in libraries for Arm64 (example).





See Improving Arm64 Performance in .NET 5.0 for more details.

Hardware intrinsics are a low-level performance feature we added in .NET Core 3.0. At the time, we added support for x86-64 instructions and chips. As part of .NET 5.0, we are extending the feature to support Arm64. Just creating the intrinsics doesn’t help performance. They need to be used in performance-critical code. We’ve taken advantage of Arm64 intrinsics extensively in .NET libraries in .NET 5.0. You can also do this in your own code, although you need to be familiar with CPU instructions to do so.



I’ll explain how hardware intrinsics work with an analogy. For the most part, developers rely on types and APIs built into .NET, like string.Split or HttpClient. Those APIs often take advantage of native operating system APIs, via the P/Invoke feature. P/Invoke enables high-performance native interop and is used extensively in the .NET libraries for that purpose. You can use this same feature yourself to call native APIs. Hardware intrinsics are similar, except instead of calling operating system APIs, they enable you to directly use CPU instructions in your code. It’s roughly equivalent to a .NET version of C++ intrinsics. Hardware intrinsics are best thought of as a CPU hardware-acceleration feature. They provide very tangible benefits and are now a key part of the performance substrate of the .NET libraries, and responsible for many of the benefits you can read about in the .NET 5.0 performance post. In terms of comparison to C++, when .NET intrinsics are AOT-compiled into Ready-To-Run files, the intrinsics have no runtime performance penalty.


Note: The Visual C++ compiler has an analogous intrinsics feature. You can directly compare C++ to .NET hardware intrinsics, as you can see if you search for _mm_i32gather_epi32 at System.Runtime.Intrinsics.X86.Avx2, x64 (amd64) intrinsics list, and Intel Intrinsics guide. You will see a lot of similarity.

注意:Visual C++编译器具有类似的本质特征。您可以直接比较C++到.NET硬件内部,如您可以看到,如果您在搜索System.Runtime.Intrinsics.X86.Avx2、x64(amd64)内部函数列表和英特尔内部函数指南。你会发现很多相似之处。

We’re making our first big investments in Arm64 performance in 5.0, and we’ll continue this effort in subsequent releases. We work directly with engineers from Arm Holdings to prioritize product improvements and to design algorithms that best take advantage of the Armv8 ISA. Some of these improvements will accrue value to Arm32, however, we are not applying unique effort to Arm32. If you use a Raspberry Pi, you’ll enjoy these improvements if you install the new Arm64 version of Raspberry Pi OS.
我们将在5.0版中对Arm64性能进行首次大投资,并将在后续版本中继续此项工作。我们直接与Arm Holdings的工程师合作,确定产品改进的优先级,并设计最充分利用Armv8 ISA的算法。这些改进中的一些将为Arm32带来价值,但是,我们并没有对Arm32做出独特的努力。如果您使用的是Raspberry Pi,那么如果您安装了新的Arm64版本的Raspberry PiOS,您将享受这些改进。

We expect that Apple will announce new Apple Silicon-based Mac computers any day now. We already have early builds of .NET 6.0 for Apple Silicon and have been working with Apple engineers to help optimize .NET for that platform. We’ve also had some early community engagement on Apple Silicon (Credit @snickler).

我们预计苹果随时都会发布新的基于苹果硅的Mac电脑。我们已经为Apple Silicon开发了早期的.NET6.0版本,并一直在与苹果工程师合作,帮助为该平台优化.NET。我们也有一些关于苹果硅的早期社区活动(Credit@snickler)。

P95+ Latency/P95+延迟
We see an increasing number of large internet-facing sites and services being hosted on .NET. While there is a lot of legitimate focus on the requests per second (RPS) metric, we find that no big site owners ask us about that or require millions of RPS. We hear a lot about latency, however, specifically about improving P95 or P99 latency. Often, the number of machines or cores that are provisioned for (and biggest cost driver of) a site are chosen based on achieving a specific P95 metric, as opposed to say P50. We think of latency as being the true “money metric”.


Our friends at Stack Overflow do a great job of sharing data on their service. One of their engineers, Nick Craver, recently shared improvements they saw to latency, as a result of moving to .NET Core:

我们在Stack Overflow的朋友在共享他们的服务上的数据方面做得很好。他们的一位工程师尼克·克雷弗(Nick Craver)最近分享了他们发现的延迟改进,这是迁移到.NET核心的结果:

The median page render time for questions dropped from about 21 ms (we were up a bit lately due to GC) to ~15ms.

The 95th percentile dropped from ~40ms to ~30ms (same measurement). 99th dropped from ~60ms to ~45ms.

Not too shabby, given we haven’t optimized anything at all yet.

— Nick Craver (@Nick_Craver) March 31, 2020

Pinned objects have been a long-term challenge for GC performance, specifically because they accelerate (or cause) memory fragmentation. We’ve added a new GC heap for pinned objects. The pinned object heap is based on the assumption that there are very few pinned objects in a process but that their presence causes disproportionate performance challenges. It makes sense to move pinned objects — particularly those created by .NET libraries as an implementation detail — to a unique area, leaving the generational GC heaps with few or no pinned objects, and with substantially higher performance as a result.


More recently, we’ve been attacking long-standing challenges in the GC. dotnet/runtime #2795 applies a new approach to GC statics scanning that avoids lock contention when it is determining liveness of GC heap objects. dotnet/runtime #25986 uses a new algorithm for balancing GC work across cores during the mark phase of garbage collection, which should increase the throughput of garbage collection with large heaps, which in turn reduces latency.


Improving tiered compilation performance/提高分层编译性能
We’ve been working on improving tiered compilation for multiple releases. We continue to see it as a critical performance feature, for both startup and steady-state performance. We’ve made two big improvements to tiered compilation this release.


The primary mechanism underlying tiered compilation is call counting. Once a method is called n times, the runtime asks the JIT to recompile the method at higher quality. From our earliest performance analyses, we knew that the call-counting mechanism was too slow, but didn’t see a straightforward way to resolve that. As part of .NET 5.0, we’ve improved the call counting mechanism used by tiered JIT compilation to smooth out performance during startup. In past releases, we’ve seen reports of unpredictable performance during the first 10-15s of process lifetime (mostly for web servers). That should now be resolved.


Another performance challenge we found was using tiered compilation for methods with loops. The fundamental problem is that you can have a cold method (only called once or a few times; $lt; n) with a loop that iterates many times. We call this pathological scenario “cold method; hot loop”. It is easy to imagine this happening with the Main method of an application. As a result, we disabled tiered compilation for methods with loops by default. Instead, we enabled applications to opt into using tiered compilation with loops. PowerShell is an application that chose to do this, after seeing high single-digit performance improvements in some scenarios.


To address methods with loops better, we implemented on-stack replacement (OSR). This is similar to a feature that the Java Virtual Machines has, of the same name. OSR enables code executed by a currently running method to be re-compiled in the middle of method execution, while those methods are active “on-stack”. This feature is currently experimental and opt-in, and on x64 only.


To use OSR, multiple features must be enabled. The PowerShell project file is a good starting point. You will notice that tiered compilation and all quick-jit features are enabled. In addition, you need to set the COMPlus_TC_OnStackReplacement environment variable to 1.

要使用OSR,必须启用多个功能。PowerShell项目文件是一个很好的起点。您将注意到,分层编译和所有quick jit功能都已启用。此外,还需要将COMPlus_TC_OnStackReplacement环境变量设置为1。

Alternatively, you can set the following two environment variables, assuming all other settings have their default values:




We do not intend to enable OSR by default in .NET 5.0 and have not yet decided if we will support it in production.


Support for ICU on Windows/在Windows上支持ICU
We use the ICU library for Unicode and globalization support, previously only on Linux and macOS. We are now using this same library on Windows 10. This change makes the behavior of globalization APIs such as culture-specific string comparison consistent between Windows 10, macOS, and Linux. We also use ICU with Blazor WebAssembly.

我们使用ICU库来支持Unicode和全球化,以前只在Linux和macOS上使用。我们现在在Windows 10上使用相同的库。此更改使全球化API的行为(如特定于区域性的字符串比较)在Windows 10、macOS和Linux之间保持一致。我们还将ICU与Blazor WebAssembly一起使用。

Expanding System.DirectoryServices.Protocols to Linux and macOS/扩大System.DirectoryServices.Protocols.协议到Linux和macOS
We’ve been adding cross-platform support for System.DirectoryServices.Protocols. This includes support for Linux and support for macOS. Windows support was pre-existing.

System.DirectoryServices.Protocols is a lower-level API than System.DirectoryServices, and enables (or can be used to enable) more scenarios. System.DirectoryServices includes Windows-only concepts/implementations, so it was not an obvious choice to make cross-platform. Both API-sets enable controlling and interacting with a directory service server, like LDAP or Active Directory.

我们已经添加了跨平台支持System.DirectoryServices.Protocols.协议. 这包括对Linux的支持和对macOS的支持。Windows支持是预先存在的。


System.Text.Json has been significantly improved in .NET 5.0 to improve performance, reliability, and to make it easier for people to adopt that are familiar with Newtonsoft.Json. It also includes support for deserializing JSON objects to records.

System.Text.Json文件在.NET5.0中得到了显著的改进,以提高性能、可靠性,并使人们更容易采用熟悉的Newtonsoft.Json. 它还支持将JSON对象反序列化为记录。

If you are looking at using System.Text.Json as an alternative to Newtonsoft.Json, you should check out the migration guide. The guide clarifies the relationship between these two APIs. System.Text.Json is intended to cover many of the same scenarios as Newtonsoft.Json, but it’s not intended to be a drop-in replacement for or achieve feature parity with the popular JSON library. We try to maintain a balance between performance and usability, and bias to performance in our design choices.


HttpClient extension methods
JsonSerializer extension methods are now exposed on HttpClient and greatly simplify using these two APIs together. These extension methods remove complexity and take care of a variety of scenarios for you, including handling the content stream and validating the content media type. Steve Gordon does a great job of explaining the benefits in Sending and receiving JSON using HttpClient with System.Net.Http.Json.


The following example deserializes weather forecast JSON data into a Forecast record, using the new


This code is compact! It is relying on top-level programs and records from C# 9 and the new GetFromJsonAsync() extension method. The use of foreach and await in such close proximity might be make you wonder if we’re going to add support for streaming JSON objects. I really hope so.


You can try this on your own machine. The following .NET SDK commands will create a weather forecast service using the WebAPI template. It will expose the service at the following URL by default: https://localhost:5001/WeatherForecast. This is the same URL used in the sample.


rich@thundera ~ % dotnet new webapi -o webapi
rich@thundera ~ % cd webapi
rich@thundera webapi % dotnet run
Make sure you’ve run dotnet dev-certs https --trust first or the handshake between client and server won’t work. If you’re having trouble, see Trust the ASP.NET Core HTTPS development certificate.

请确保您已经运行了dotnet dev certs https–trust first,否则客户端和服务器之间的握手将无法工作。如果你遇到麻烦,请参见信任ASP.NET核心HTTPS开发证书。

You can then run the previous sample.


rich@thundera ~ % git clone weather-forecast
rich@thundera ~ % cd weather-forecast
rich@thundera weather-forecast % dotnet run
9/9/2020 12:09:19 PM; 24C; Chilly9/10/2020 12:09:19 PM; 54C; Mild9/11/2020 12:09:19 PM; -2C; Hot9/12/2020 12:09:19 PM; 24C; Cool9/13/2020 12:09:19 PM; 45C; Balmy
Improved support for immutable types

There are multiple patterns for defining immutable types. Records are just the newest one. JsonSerializer now has support for immutable types.

In this example, you’ll see the serialization with an immutable struct.



using System;using System.Text.Json;using System.Text.Json.Serialization;var json = "{“date”:“2020-09-06T11:31:01.923395-07:00”,“temperatureC”:-1,“temperatureF”:31,“summary”:“Scorching”} ";
var options = new JsonSerializerOptions(){
PropertyNameCaseInsensitive = true,
IncludeFields = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase};var forecast = JsonSerializer.Deserialize(json, options);Console.WriteLine(forecast.Date);Console.WriteLine(forecast.TemperatureC);Console.WriteLine(forecast.TemperatureF);Console.WriteLine(forecast.Summary);var roundTrippedJson = JsonSerializer.Serialize(forecast, options);Console.WriteLine(roundTrippedJson);public struct Forecast{
public DateTime Date {get;}
public int TemperatureC {get;}
public int TemperatureF {get;}
public string Summary {get;}
public Forecast(DateTime date, int temperatureC, int temperatureF, string summary) => (Date, TemperatureC, TemperatureF, Summary) = (date, temperatureC, temperatureF, summary);}
Note: The JsonConstructor attribute is required to specify the constructor to use with structs. With classes, if there is only a single constructor, then the attribute is not required. Same with records.


It produces the following output:


rich@thundera jsonserializerimmutabletypes % dotnet run
9/6/2020 11:31:01 AM
Support for records/记录支持
JsonSerializer support for records is almost the same as what I just showed you for immutable types. The difference I want to show here is deserializing a JSON object to a record that exposes a parameterized constructor and an optional init property.


Here’s the program, including the record definition:


It produces the following output:


rich@thundera jsonserializerrecords % dotnet run
{“Date”:“2020-09-12T18:24:47.053821-07:00”,“TemperatureC”:40,“Summary”:“Hot!”}Forecast { Date = 9/12/2020 6:24:47 PM, TemperatureC = 40, Summary = Hot! }
Improved Dictionary<K,V> support
JsonSerializer now supports dictionaries with non-string keys. You can see what this looks like in the following sample. With .NET Core 3.0, this code compiles but throws a NotSupportedException.



It produces the following output.


rich@thundera jsondictionarykeys % dotnet run
{“0”:“zero”,“1”:“one”,“2”:“two”,“3”:“three”,“5”:“five”,“8”:“eight”,“13”:“thirteen”,“21”:“twenty one”,“34”:“thirty four”,“55”:“fifty five”}
fifty five
Support for fields/对字段的支持
JsonSerializer now supports fields. This change was contributed by @YohDeadfall. Thanks!


You can see what this looks like in the following sample. With .NET Core 3.0, JsonSerializer fails to serialize or deserialize with types that use fields. This is a problem for existing types that have fields and cannot be changed. With this change, that’s no longer an issue.


Produces the following output:


rich@thundera jsonserializerfields % dotnet run
9/6/2020 11:31:01 AM
Preserving references in JSON object graphs/在JSON对象图中保存引用
JsonSerializer has added support for preserving (circular) references within JSON object graphs. It does this by storing IDs that can be reconstituted when a JSON string is deserialized back to objects.


JsonSerializer performance is significantly improved in .NET 5.0. Stephen Toub covered some JsonSerializer improvements in his Performance Improvements in .NET 5 post. I also covered Json Performance in more detailed in the .NET 5.0 RC1 post.


Application deployment/应用程序部署
After writing or updating an application, you need to deploy it for your users to benefit. This might be to a web server, a cloud service, or client machine, and might be the result of a CI/CD flow using a service like Azure DevOps or GitHub Actions.

在编写或更新应用程序之后,您需要部署它以使您的用户受益。这可能是web服务器、云服务或客户端计算机的结果,也可能是使用Azure DevOps或GitHub操作之类的服务的CI/CD流的结果。

We strive to provide first-class deployment capabilities that naturally align with the application types. For .NET 5.0, we focused on improving single file applications, reducing container size for docker multi-stage builds, and providing better support for deploying ClickOnce applications with .NET Core.


We consider containers to be the most important cloud trend and have been investing significantly in this modality. We’re investing in containers in multiple ways, at multiple levels of the .NET software stack. The first is our investment in fundamentals, which is increasingly influenced by the container scenario and by developers who deploy containerized apps.


We’re making it easier to work with container orchestrators. We’ve added OpenTelemetry support so that you can capture distributed traces and metrics from your application. dotnet-monitor is a new tool that is intended as the primary way to access diagnostic information from a .NET process. In particular, we have started building a container variant of dotnet-monitor that you can use as an application sidecar. Last, we are building dotnet/tye as way to improve microservices developer productivity, both for development and deploying to a Kubernetes environment.


The .NET runtime now has support for cgroup v2, which we expect will become an important container-related API beyond 2020. Docker currently uses cgroup v1 (which is already supported by .NET). In comparison, cgroup v2 is simpler, more efficient, and more secure than cgroup v1. You can learn more about cgroup and Docker resource limits from our 2019 Docker update. Linux distros and containers runtimes are in the process of adding support for cgroup v2. .NET 5.0 will work correctly in cgroup v2 environments once they become more common. Credit to Omair Majid, who supports .NET at Red Hat.


We’re now publishing Windows Server Core images, in addition to Nano Server. We added Server Core because we heard feedback from customers who wanted a .NET image that was fully compatible with Windows Server. If you need that, then this new image is for you. It’s supported for the combination of: Windows Server 2019 Long-Term Servicing Channel (LTSC), .NET 5.0, and x64. We’ve made other changes that reduce the size of Windows Server Core images. Those improvements make a big difference but were made after Windows Server 2019 was released. They will, however, benefit the next Windows Server LTSC release.

我们现在发布的是Windows Server核心映像,除了Nano服务器。我们添加了服务器核心,因为我们听到了来自客户的反馈,他们希望有一个与Windows Server完全兼容的.NET映像。如果你需要,那么这个新的图像是给你的。它支持:Windows Server 2019长期服务通道(LTSC)、.NET 5.0和x64的组合。我们做了其他的更改,以减少Windows Server核心映像的大小。这些改进有很大的不同,但在Windows Server 2019发布之后进行了改进。但是,它们将有利于下一个Windows Server LTSC版本。

As part of the move to “.NET” as the product name, we’re now publishing .NET Core 2.1, 3.1 and .NET 5.0 images to the family of repos, instead of We will continue dual publishing .NET Core 2.1 and 3.1 to the previous location while those versions are supported. .NET 5.0 images will only be published to the new locations. Please update your FROM statements and scripts accordingly.

作为将.NET作为产品名称的一部分,我们现在将.NET Core 2.1、3.1和.NET 5.0映像发布到回购家族,而不是 我们将继续将.NET Core 2.1和3.1双重发布到以前的位置,同时支持这些版本。NET5.0图像将只发布到新的位置。请相应地更新您的FROM语句和脚本。

As part of .NET 5.0, we re-based the SDK image on top of the ASP.NET image instead of buildpack-deps to dramatically reduces the size of the aggregate images you pull in multi-stage build scenarios.

This change has the following benefit for multi-stage builds, with a sample Dockerfile:

作为.NET5.0的一部分,我们将SDK映像基于ASP.NETimage而不是buildpack deps可以显著减少在多阶段构建场景中拉取的聚合映像的大小。


Multi-stage build costs with Ubuntu 20.04 Focal:

Ubuntu 20.04 Focal的多阶段构建成本:

Pull Image Before After
sdk:5.0-focal 268 MB 232 MB
aspnet:5.0-focal 64 MB 10 KB (manifest only)
Net download savings: 100 MB (-30%)

净下载节省:100 MB(-30%)

Multi-stage build costs with Debian 10 Buster:

Debian 10 Buster的多阶段构建成本:

Pull Image Before After
sdk:5.0 280 MB 218 MB
aspnet:5.0 84 MB 4 KB (manifest only)
Net download savings: 146 MB (-40%)

净下载节省:146 MB(-40%)

See dotnet/dotnet-docker #1814 for more detailed information.

This change helps multi-stage builds, where the sdk and the aspnet or runtime image you are targeting are the same version (we expect that this is the common case). With this change, the aspnet pull (for example), will be a no-op, because you will have pulled the aspnet layers via the initial sdk pull.

有关详细信息,请参见dotnet/dotnet docker#1814。

此更改有助于多阶段构建,其中sdk和aspnet或运行时映像的版本相同(我们希望这是常见的情况)。有了这个更改,aspnet pull(例如)将成为一个no-op,因为您将通过初始sdk pull拉取aspnet层。

We made similar changes for Alpine and Nano Server. There is no buildpack-deps image for either Alpine or Nano Server. However, the sdk images for Alpine and Nano Server were not previously built on top of the ASP.NET image. We fixed that. You will see significant size wins for Alpine and Nano Server as well with 5.0, for multi-stage builds.

我们对Alpine和Nano服务器进行了类似的更改。对于Alpine或Nano服务器,没有buildpack deps映像。但是,Alpine和Nano服务器的sdk映像以前并不是建立在NET.ASP图像。我们修好了。您将看到Alpine和Nano服务器以及5.0多阶段构建的重大规模胜利。

Single file applications/单文件应用程序
Single file applications are published and deployed as a single file. The app and its dependencies are all included within that file. When the app is run, the dependencies are loaded directly from that file into memory (with no performance penalty).


In .NET 5.0, single file apps are primarily focused on Linux (more on that later). They can be either framework-dependent or self-contained. Framework-dependent single file apps can be very small, by relying on a globally-installed .NET runtime. Self-contained single-file apps are larger (due to carrying the runtime), but do not require installation of the .NET runtime as an installation pre-step and will just work as a result. In general, framework-dependent is good for development and enterprise environments, while self-contained is often a better choice for ISVs.


We produced a version of single-file apps with .NET Core 3.1. It packages binaries into a single file for deployment and then unpacks those files to a temporary directory to load and execute them. There may be some scenarios where this approach is better, but we expect that the solution we’ve built for 5.0 will be preferred and a welcome improvement.


We had multiple hurdles to overcome to create a true single-file solution. Key tasks were creating a more sophisticated application bundler and teaching the runtime to load assemblies out of binary resources. We also ran into some hurdles that we could not clear.


On all platforms, we have a component called “apphost”. This is the file that becomes your executable, for example myapp.exe on Windows or ./myapp on Unix-based platforms. For single file apps we created a new apphost we call “superhost”. It has the same role as the regular apphost, but also includes a statically-linked copy of the runtime. The superhost is a fundamental design point of our single file approach. This model is the one we use on Linux with .NET 5.0. We were not able to implement this approach on Windows or macOS, due to various operating system constraints. We do not have a superhost on Windows or macOS. On those operating systems, the native runtime binaries (~3 of them) sit beside the single file app (resulting in “not single file”). We’ll revisit this situation in .NET 6.0, however, we expect the problems we ran into to remain challenging.


You can use the following commands to produce single-file apps.


Framework-dependent single-file app:

dotnet publish -r linux-x64 --self-contained false /p:PublishSingleFile=true

Self-contained single-file app:

dotnet publish -r linux-x64 --self-contained true /p:PublishSingleFile=true

You can also configure single file publishing with a project file.


Exe net5.0 linux-x64 true true You can experiment with assembly trimming to reduce the size of your application. It can break apps, by over-trimming, so it is recommended to test your app thoroughly after using this feature. Assembly trimming also removes ahead-of-time-compiled read-to-run native code (for the assemblies that are trimmed), which is there primarily for performance. You will want to test your application for performance after trimming. You can ready-to-run-compile your app after trimmng by using PublishReadyToRun property (and setting to true).



Apps are OS and architecture-specific. You need to publish for each configuration (Linux x64, Linux Arm64, Windows x64, …).

Configuration files (like *.runtimeconfig.json) are included in the single file. You can place an additional config file beside the single file, if needed (possibly for testing).

.pdb files are not included in the single file by default. You can enable PDB embedding with the embed property.

The IncludeNativeLibrariesForSelfExtract property can be used to embed native runtime binaries, on Windows and macOS, however, they have to be unpacked to temporary storage at runtime. This feature is not recommended for genereal use.


应用程序是操作系统和体系结构特有的。您需要为每个配置(Linux x64、Linux Arm64、Windows x64…)发布。




ClickOnce has been a popular .NET deployment option for many years. It’s now supported for .NET Core 3.1 and .NET 5.0 Windows apps. We knew that many people would want to use ClickOnce for application deployment when we added Windows Forms and WPF support to .NET Core 3.0. In the past year, the .NET and Visual Studio teams worked together to enable ClickOnce publishing, both at the command line and in Visual Studio.

ClickOnce多年来一直是一个流行的.NET部署选项。现在.NET Core 3.1和.NET 5.0 Windows应用程序支持它。我们知道,当我们将Windows窗体和WPF支持添加到.NETCore3.0时,许多人都希望使用ClickOnce进行应用程序部署。在过去的一年中,.NET和visualstudio团队合作,在命令行和visualstudio中启用ClickOnce发布。

We had two goals from the start of the project:


Enable a familiar experience for ClickOnce in Visual Studio.

Enable a modern CI/CD for ClickOnce publishing with command-line flows, with either MSBuild or the Mage tool.

It’s easiest to show you the experience in pictures.


Let’s start with the Visual Studio experience, which is centered around project publishing.


The primary deployment model we’re currently supporting is framework dependent apps. It is easy to take a dependency on the .NET Desktop Runtime (that’s the one that contains WPF and Windows Forms). Your ClickOnce installer will install the .NET runtime on user machines if it is needed. We also intend to support self-contained and single file apps.


You might wonder if you can still be able to take advantage of ClickOnce offline and updating features. Yes, you can.


The big change with Mage is that it is now a .NET tool, distributed on NuGet. That means you don’t need to install anything special on your machine. You just need the .NET 5.0 SDK and then you can install Mage as a .NET tool. You can use it to publish .NET Framework apps as well, however, SHA1 signing and partial trust support have been removed.

Mage的最大变化是它现在是一个.NET工具,分布在NuGet上。这意味着你不需要在你的机器上安装任何特殊的东西。您只需要.NET5.0SDK,然后就可以将Mage安装为.NET工具。您也可以使用它发布.NET Framework应用程序,但是,SHA1签名和部分信任支持已被删除。

The Mage installation command follows:


dotnet tool install -g Microsoft.DotNet.Mage
After you’ve produced and distributed your ClickOnce installer, your users will see the familiar ClickOnce installation dialogs.


Your users will see the update dialog when you make updates available.


.NET 5.0 is another big release that should improve many aspects of your use with .NET. We have enabled a broad set of improvements, ranging from single file applications, to performance, to Json serialization usability to Arm64 enablement. While today may be your first day with .NET 5.0, we’ve been running .NET 5.0 in production at Microsoft for months. We have confidence that it is ready for you to use, to run your business and power your apps. The new language improvements in C# 9 and F# 5 should make your code more expressive and easier to write. .NET 5.0 is also a great choice for your existing apps. In many cases, you can upgrade without much effort.

If you’re interested in performance, you may be interested in our progress with the TechEmpower benchmarks. Looking back, you can see that .NET Core 3.1 is doing pretty well with round 19, the latest round. We’re looking forward to seeing .NET 5.0 in the upcoming round 20. The new ranking will be something to watch out for when round 20 is finalized and published.

The improvements in .NET 5.0 are the result of efforts by many people, working collaboratively across the world and in many time zones, on GitHub. Thanks to everyone who contributed to this release. And don’t worry, there are lots of opportunities to contribute. The .NET 5.0 release has come to a close, but the next release has already started.






  • 0
  • 0
  • 0
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
钱包余额 0