今天,.NET 5预览8发布了,对于.NET5.0的功能开发已经完成了,这必须要排除待处理的bug,预览8是最后一次预览版本。预计11月正式的.NET5.0版本发布之前还将发布两个正式之前的候选版本,这篇文章描述了.NET5.0版本中的一系列功能。 You can download .NET 5.0, for Windows, macOS, and Linux:
- Installers and binaries
- Container images
- Snap installer
- Release notes
- Known issues
- GitHub issue tracker
今天同时也发布了ASP.NET Core 和 EF Core 。 要使用.NET5我们需要最新版本的 Visual Studio (包括 Visual Studio for Mac) 才能使用 .NET 5.0. .NET 5.0包括许多改进,特别是单个文件应用程序,较小的容器映像,更强大的JsonSerializer API,一整套可空的引用类型注释以及对Windows ARM64的支持。在NET库,GC和JIT中,性能得到了极大的提高。ARM64是性能投资的重点,可提高吞吐量并减少二进制文件。.NET 5.0包括新的语言版本C#9和F#5.0。 .NET 5.0包括了许多的改进,特别是单个文件应用程序,较小的容器映像,更强大的JsonSerializer APIs,一整套可空的引用类型注释以及对Windows ARM64的支持。在.NET库,GC和JIT中,性能得到了极大的提高,ARM6是性能的重点项,可提高吞吐量并减少二进制文件。.NET5.0包括新的语言版本C# 9 和F# 5.0. 现在这个版本功能开发已经完成,让我们看一下.NET5.0的一部分,该帖子由一组主题部分组成:语言,工具、API、运行时技术和应用程序部署。这些部分及其顺序大致反映了开发过程和生命周期,如果您对一个开发方面对比另一个方面更敢兴趣,这将帮助您找到所需的内容。
Languages
C#9和F#5是.NET5.0版本的一部分,并包含在.NET5.0 SDK中,Visual SDK也包含了在5.0 SDK中,它不包括语言的更改,但进行了改进以支持.NET Core上的Visual Basic应用程序框架。 C#源码生成器是一项重要的新c#编译器新功能,由于它没有任何语言语法,因此在技术上不属于C#9,请参阅新的c#源代码生成器示例,以帮助您开始使用此新功能。
C# 9
c#9是该语言的重要版本,这个版本专注于程序的简单性,数据不变形和更多的模式.
Top-level programs
高级的程序提供了更简单的语法,而仪式感却变少了,此语法将首先帮助我们学习该语言,我们希望高级程序语法在后续发行版中变得更加简单,例如删除默认的 using
语句
下面是c# 9版本的“hello world”。
using System;
Console.WriteLine("Hello World!");
高级的程序可以扩展为使用更多功能,例如在同一文件中定义和调用方法或者类.
代码语言:javascript复制using System;
using System.Runtime.InteropServices;
Console.WriteLine("Hello World!");
FromWhom();
Show.Excitement("Top-level programs can be brief, and can grow as slowly or quickly in complexity as you'd like", 8);
void FromWhom()
{
Console.WriteLine($"From {RuntimeInformation.FrameworkDescription}");
}
internal class Show
{
internal static void Excitement(string message, int levelOf)
{
Console.Write(message);
for (int i = 0; i < levelOf; i )
{
Console.Write("!");
}
Console.WriteLine();
}
}
该程序生成以下输出。
代码语言:javascript复制[rich@taumarunui test]$ ~/dotnet/dotnet run
Hello World!
From .NET 5.0.0-preview.8
Top-level programs can be brief, and can grow as slowly or quickly in complexity as you'd like!!!!!!!!
Pattern matching
Patterns test值具有特定的形状,并在其具有匹配形状时可以从值中提取信息。最新的c#版本中已添加了新的模式匹配改进。 我将分享两个示例,第一个演示了属性的模式,在将上下文对象与特定模式进行比较之前,他会检查是否为null(带有is).
代码语言:javascript复制if (context is {IsReachable: true, Length: > 1 })
{
Console.WriteLine(context.Name);
}
This is equivalent to:
if (context is object && context.IsReachable && context.Length > 1 )
{
Console.WriteLine(context.Name);
}
Also equivalent to:
if (context?.IsReachable && context?.Length > 1 )
{
Console.WriteLine(context.Name);
}
以下示例使用relational patterns(如<,<=)和逻辑模式(如and,or和not)。以下代码根据毛重计算出送货的卡车在高速公路的通行费(decimal
),对于那些不熟悉的人,在数字文字告诉编译器之后,m表示数字是decimal
而不是double
.
DeliveryTruck t when t.GrossWeightClass switch
{
< 3000 => 8.00m,
>= 3000 and <= 5000 => 10.00m,
> 5000 => 15.00m,
},
Target-typed new
expressions
Target-typed new
expressions是在构造对象/值时移除类型重复的一种新方法。
下面的示例都是等效的,中间是新的语法。
List<string> values = new List<string>();
List<string> values = new();
var values = new List<string>();
我猜很多人都会喜欢这个新语法 var
有两个原因:许多人阅读从左到右和希望的类型信息左边 =
,可能更重要的是左边的事完全致力于类型信息,而不是被一个特定的构构造函数的复杂性和细微差别(右边)
Tools
在这篇文章中,我们将重点关注运行时诊断工具。
Microsoft.Extensions.Logging
我们对Microsoft.Extensions.Logging
库中的控制台日志提供程序进行了改进,开发人员现在可以实现自定义的[ConsoleFormatt](https://github.com/dotnet/runtime/issues/34742)
,以完全控制控制台输出的格式和颜色,格式化程序API通过实现 VT-100
(大多数现代终端支持)转移序列的子集来实现丰富的格式化,控制台记录器可以解析不受支持的终端上的转义序列,使您可以为所有终端编写单个格式化程序。
除了支持自定义格式化程序外,我们还添加了一个内置的JSON格式化程序,它会将结构化JSON日志发送到控制台。
Dump debugging
调试托管代码需要对托管对象和构造有特殊的了解,数据访问组件(DAC)事运行时执行引擎的子集,他具有这些构造的知识,并且可以在没有运行时的情况下访问这些托管对象,从Preview 8开始,他们已经开始针对Windows编译Linux DAC,现在可以使用WinDBG或 dotnet dump analysis
在Windows上分析在Linux上收集的.NET Core进程转储。
在Preview 8中,我们还添加了对从macOS上运行的.NET进程捕获ELF转储的支持,由于ELF并不是macOS上的本机可执行文件(像 lldvb
这样本地调试器将不适用于这些转储)文件格式,因此我们将其设为可选功能,要在macOS上启用对转储收集的支持,请设置环境变量COMPlus_DbgEnableElfDumpOnMacOS=1
可以使用 dotnet dump analyze
对生成的dump进行分析
Assembly load diagnostics added to event pipe
我们向事件管道添加了程序集加载信息,您可以将其视为Fusion Log Viewer的替代品,现在您可以使用 dotnet-trace 通过以下命令来收集此信息
代码语言:javascript复制Microsoft-Windows-DotNETRuntime:4:4 --process-id [process ID]
Printing environment information
随着.NET扩展了对新操作系统和芯片体系结构的支持,人们有时需要一种打印环境信息的方法,我们创建了一个简单的.NET工具成为dotnet-runtimeinfo. 您可以使用以下命令安装和运行该工具
代码语言:javascript复制dotnet tool install -g dotnet-runtimeinfo
dotnet-runtimeinfo
该工具为您的环境生成以下形式的输出
代码语言:javascript复制[rich@taumarunui ~]$ dotnet-runtimeinfo
.NET information
Version: 5.0.0
FrameworkDescription: .NET 5.0.0-preview.8.20407.11
Libraries version: 5.0.0-preview.8.20407.11
Libraries hash: bf456654f9a4f9a86c15d9d50095ff29cde5f0a4
**Environment information
OSDescription: Linux 5.8.3-2-MANJARO-ARM #1 SMP Sat Aug 22 21:00:07 CEST 2020
OSVersion: Unix 5.8.3.2
OSArchitecture: Arm64
ProcessorCount: 6
**CGroup info
cfs_quota_us: -1
memory.limit_in_bytes: 9223372036854771712
memory.usage_in_bytes: 2945581056
Library APIs
在.NET5.0中添加并改进了许多新的api,下面是一些重要的变化,需要注意。
Nullable Annotations
可空引用类型是c#8和.NET Core3.0的重要功能,他的发布充满了希望,但缺少详细的平台注释,以使其真正有用且使用,等待(大部分)结束了,现在该平台已为可控性添加了80%的注释,他们正在研究是否可以在发布.NET5.0 RTM之前注释剩余的20%如果没有,他们将在.NET6.0的早期完成其余的注释。
下图展示了他们这段时间内取得的进展。
这也意味着,当您将现有的.NET Core3.1代码重新定位到.NET 5.0时,可能会生成新的诊断(如果启用了可空性),如果发生这种情况,您可以感谢我们帮助您避免使用 null
Regular expression performance improvements
我们对Regex引擎进行了重大的改进,在他们尝试过许多表达式中,这些改进通常会让吞吐量提高3-6倍,在某些情况下甚至更多,他们在System.Text.RegularExpressions
中所做的更改。经常的压力已经对他们自己的使用产生了可衡量的影响。他们希望这些改进也能在你的库和应用程序中带来可衡量的胜利
.NET 5.0 Target Framework
我们正在改变,.NET5.0目标框架的使用方法,下面的项目文件演示了新的.NET5.0目标框架
代码语言:javascript复制<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
到目前为止,新的.NET5.0表单比我们使用netcoreapp3.1样式更紧凑,更直观。此外他们正在将目标框架扩展为操作系统进行建模。他们希望通过.NET6.0中的Xamarin定位IOS和Android,从而推动这一变化。
Windows桌面API仅在面向net5.0-windows
时可用,您可以指定操作系统版本,例如 net5.0-windows7或
net5.0-windows10.17763
(October 2018 Update) ,如果要使用WinRT APIs.,则需要定位Windows10版本。
变动汇总:
net5.0
is the new Target Framework Moniker (TFM) for .NET 5.0.net5.0
combines and replacesnetcoreapp
andnetstandard
TFMs.net5.0
supports .NET Framework compatibility modenet5.0-windows
will be used to expose Windows-specific functionality, like Windows Forms and WPF.- .NET 6.0 will use the same approach, with
net6.0
and will addnet6.0-ios
andnet6.0-android
. - The OS-specific TFMs can include OS version numbers, like
net6.0-ios14
. - Portable APIs, like ASP.NET Core and Xamarin.Forms, will be usable with
net5.0
.
WinRT Interop (Breaking Change)
我们已经移至一个新模型,作为.NET5.0的一部分,他支持WinRT API,这包括调用API(在任一方向上; CLR <==> WinRT),两个类型系统之间的数据封送处理以及旨在跨越边界被视为相同类型的统一(既“projected types”; IEnumerable<T>
和 IIterable<T>
是示例)
他们将以来WinRT团队在Windows中提供的一套新的WinRT工具,他将生成基于c#的WinRT互操作程序集
新的WinRT互操作系统有几个好处:
- It can be developed and improved separate from the .NET runtime.
- Symmetrical with interop systems provided for other OSes, like iOS and Android.
- Can take advantage of many other .NET features (AOT, C# features, IL linking).
- Simplifies the .NET runtime codebase.
现有的WinRT互操作系统已经作为.NET5.0的一部分,从.NET运行时(以及任何其他相关组件)中删除,这是一个突破性的变化,这将意味者使用WinRT和.NET Core3.x 应用程序需要重新构建,不能按照原样在.NET5上运行。
Runtime Technology
在.NET5.0中添加了许多新特性。下面介绍一小部分选择。
Windows ARM64
我们在这个版本中增加了对Windows ARM64的支持。我们已经做出了相对较晚的决定,推迟Windows桌面组件(Windows Forms, WPF)的发布。Windows窗体已接近就绪,但WPF还没有,而且我们不想只发布Windows桌面组件的一半,部分原因是我们没有在分割配置中测试它。我们希望在5.0服务更新中添加Windows桌面组件。 我们正在与一些ISV合作,他们希望其应用程序在Windows ARM64上可用。如果符合您的情况,请通过dotnet@microsoft.com与我们联系。我们希望尽快为您提供构建版本。
Event pipe profiler APIs
事件管道是在.NET Core 2.2中添加的新子系统和API,可以在任何操作系统上执行性能和其他诊断调查。在.NET 5.0中,事件管道已得到扩展,以使事件探查器能够写入事件管道事件。对于以前依靠ETW监视应用程序行为和性能的分析探查器,此方案至关重要。
Native exports
您现在可以将托管方法导出到本机代码。该功能的构建块是托管对UnmanagedCallersOnlyAttribute的API支持。
开发团队的Aaron Robinson一直在从事.NET Native Exports项目,该项目为将.NET组件作为本机库发布提供了更完整的体验。我们正在寻求有关此功能的反馈,以帮助决定是否在更高版本中将该方法包括在产品中。
有一些现有的项目可以实现类似的场景,例如:
- Unmanaged Exports
- DllExport
Application deployment
编写或更新应用程序后,您需要对其进行部署以供用户利用。在此版本中,我们专注于单个文件应用程序,并改进了.NET Core的ClickOnce。
Single file applications
单个文件应用程序作为单个文件发布和部署。该应用程序及其依赖项都包含在该文件中。当应用程序运行时,依赖项直接从该文件加载到内存中。这种方法不会降低性能。当与程序集修剪和提前编译结合使用时,单个文件应用程序将变得更小,启动速度更快。 在.NET 5.0中,单个文件应用程序主要集中在Linux上(稍后会详细介绍)。它们可以是框架相关的,也可以是独立的。依赖于全局安装的.NET运行时,依赖于框架的单个文件应用程序可能很小。自包含的单文件应用程序更大(由于带有运行时),但是不需要作为安装前步骤就安装.NET运行时,因此可以正常工作。通常,依赖框架对开发和企业环境有利,而对于ISV,独立包含通常是更好的选择。 我们使用.NET Core 3.1制作了一个单文件应用程序版本。它将二进制文件打包到一个文件中以进行部署,然后将这些文件解压缩到一个临时目录中以加载并执行它们。在某些情况下,这种方法可能会更好,但是我们希望我们为5.0构建的解决方案将是首选,并且会受到欢迎。 创建真正的单文件解决方案需要克服多个障碍。我们必须创建一个更复杂的应用程序捆绑器,教导运行时从二进制资源中加载程序集,并使调试器与内存映射的程序集兼容。我们还遇到了一些我们无法清除的障碍。
在所有平台上,我们都有一个名为“ apphost”的组件。这是成为可执行文件的文件,例如Windows上的 myapp.exe
或基于Unix平台上的 ./myapp
。对于单文件应用程序,我们创建了一个新主机,称为“超级主机”。它具有与常规apphost相同的角色,但还包含运行时的静态链接副本。超级主机是我们单文件方法的基本设计要点。此模型是我们在Linux上使用的模型。由于各种操作系统限制,我们无法在Windows或macOS上实现此方法。在Windows或macOS上没有超级主机。在这些操作系统上,本机运行时二进制文件(约3个)位于单个文件应用程序旁边。我们将在.NET 6.0中重新审视这种情况,但是,我们希望遇到的问题仍然具有挑战性。
您可以使用以下命令生成单文件应用程序。
- Framework-dependent single-file app:
dotnet publish -r linux-x64 --self-contained false /p:PublishSingleFile=true
- Self-contained single-file app with assembly trimming and ready to run enabled:
dotnet publish -r linux-x64 --self-contained true /p:PublishSingleFile=true /p:PublishTrimmed=true /p:PublishReadyToRun=true
您还可以使用项目文件配置单个文件发布。
代码语言:javascript复制<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<!-- Enable single file -->
<PublishSingleFile>true</PublishSingleFile>
<!-- Determine self-contained or framework-dependent -->
<SelfContained>true</SelfContained>
<!-- The OS and CPU type you are targeting -->
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<!-- Enable use of assemby trimming - only supported for self-contained apps -->
<PublishTrimmed>true</PublishTrimmed>
<!-- Enable AOT compilation -->
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
</Project>
Notes:
- 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<DebugType>embed</DebugType>
property.
我们在以前的预览文章中看到了很多评论,询问有关单个文件应用程序与提前(AOT)编译之间的关系。AOT是一个频谱。dotnet发布生成的现成代码(将 PublishReadyToRun
设置为true时)是AOT的示例。当您发布准备运行的映像时,该构建会提前为您生成机器代码,而不是在运行时由JIT生成。大多数人可能会将其作为AOT的定义。但是,许多人说AOT时的意思更具体。他们想要一种具有以下特征的解决方案:启动速度极快,不存在IL(出于大小和混淆的原因),(最多)JIT是可选的,并且二进制大小尽可能小。我们使用术语“本机AOT”来描述AOT频谱上的该点。.NET 5.0中提供的单个文件解决方案不满足AOT的这一定义。这是一大进步,但不是“本地AOT”。我们最近发布了有关本机AOT的调查,以获取有关该模式的更多反馈。我们正在仔细研究结果,并将其纳入我们的6.0计划工作中。
Reducing the size of container images
我们一直在寻找使.NET容器映像更小且更易于使用的机会。我们将SDK映像重新建立在ASP.NET映像之上,而不是buildpack-deps上,以显着减小您在多阶段构建方案中提取的聚合映像的大小
对于多阶段构建,此更改具有以下优势(Dockerfile中的示例用法) Multi-stage build costs with 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%) Multi-stage build costs with 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%)
See dotnet/dotnet-docker #1814 for more detailed information.
此更改有助于多阶段构建,其中目标的sdk和aspnet或运行时映像是同一版本(我们希望这是常见的情况)。进行此更改后,aspnet pull(例如)将变为无操作状态,因为您将通过初始sdk pull来拉伸aspnet层。
我们对Alpine和Nano Server进行了类似的更改。对于Alpine或Nano Server,没有 buildpack-deps
映像。但是,Alpine和Nano Server的sdk映像以前未在ASP.NET映像之上构建。我们解决了。对于多阶段构建,您将看到Alpine和Nano Server以及5.0的巨大成功。
ClickOnce Support
几个月前,我们宣布将为.NET Core提供ClickOnce支持。该项目仍在进行中。我们希望将其作为RC2的一部分提供。我只是想分享一下我们仍在从事此项目。
Closing
在发行版中,“关闭”是一个有趣的章节标题。该发布确实即将结束。该团队致力于解决所有剩余的5.0问题,并在发行版中获得最终的错误修复和改进。甚至5.0 Runtime Epics问题也已解决。 我们正在研究一些深入的帖子,我们计划在有关各种主题的最终版本发布之前发布这些帖子。注意那些。您还可以期望最终版本的发布时间更长,涵盖更广泛的改进和功能。 感谢您对本发行版的所有支持以及所做的所有贡献。