net8来了
11 月 15 日开始的为期三天的 .NET Conf 在线活动的开幕日上,.NET 8作为微软的开源跨平台开发平台正式发布。.NET 团队着重强调云、性能、全栈 Blazor、AI 和 .NET MAUI 是.NET 8的主要亮点。。NET团队在 .NET Conf 2023 [1]活动开幕式上表示:“通过这个版本,.NET 重塑了我们构建按需扩展的智能、云原生应用程序和高流量服务的方式。 无论你是部署到 Linux 还是 Windows,使用容器还是你选择的云应用模型,.NET 8 都能更轻松地构建这些应用。”
在数字化转型的智能化方向上我们可以用.NET 8 做下列这些场景:
- 将 OpenAI 的 GPT 等大型语言模型 (LLM) 直接集成到 .NET 应用中,这个主要是通过开源项目 Semantic Kernel(简称SK)。
- 使用单个功能强大的组件模型来处理 Blazor 的所有 Web UI 需求, Blazor 在.NET 8真的是成熟了,可以大力发挥全栈开发的能力了。
- 使用 .NET MAUI 将移动应用程序部署到最新版本的 iOS 和 Android,在移动应用开发方面解决多年的包袱。
- 发现新的语言增强功能,使你的代码在 C# 12 中更加简洁和富有表现力。
对企业来说特别重要的是,.NET 8 [2]是一个长期支持 (LTS) 版本,这意味着它将获得三年的支持和补丁,而标准期限支持 (STS) 版本则是 18 个月。对于开发人员来说,特别重要的是 .NET团队正在向期待已久的原生提前编译(NativeAOT)迈进 。
2020年的时候.NET团队做过一项调查中发现Survey: Native AOT [results][3],.NET Core 中缺少NativeAOT 阻碍了开发平台的采用,促使 .NET 团队大力推动 AOT。
.NET 8通过推进NativeAOT来增强可持续计算,以减少内存使用并实现即时应用程序启动,今天强调了AOT的功能,包括:
- 它将应用程序编译为使用更少内存的本机代码并立即启动
- 无需等待 JIT(实时)编译器在运行时编译代码
- 无需部署 JIT 编译器和 IL 代码
- AOT 应用仅部署应用所需的代码
- 现在,应用程序可以在不允许使用 JIT 编译器的受限环境中运行
还描述了原生 AOT 大小优化。
在描述.NET 8的整体情况时,.NET 团队表示:“NET 8提供了数千项性能,稳定性和安全性改进,以及平台和工具增强功能,有助于提高开发人员的生产力和创新速度。在公告博客[4]文章中,这数千项改进围绕上述五个主题进行了分组。以下是每个领域的介绍。
性能
.NET团队的 Stephen Toub 每年都会针对.NET性能方进行彻底、煞费苦心和详尽的详细说明,他总结了数千个性能数据点,宣称: .NET 7 速度超快, .NET 8 更快。[5]
.NET 8 引入了新的代码生成器,即动态配置文件引导优化 (PGO),它根据实际使用情况优化代码。此功能最多可将应用性能提高 20%。AVX-512 指令集支持对 512 位数据向量进行并行运算,在 .NET 8 中受支持和使用,从而允许在更短的时间内进行更多的数据处理。此外,基元类型现在实现了新的格式化和可解析接口,使它们能够直接格式化和解析为 UTF-8,而不会产生任何转码开销。这个结果可以看 TechEmpower 22轮Web框架 性能评测:.NET 8 战绩斐然的[6]说明
云原生
.NET 8 以多种方式促进了云原生开发,例如包括许多容器增强功能,但这里的重大新闻是 .NET Aspire 的第一个预览版的可用性,这是一个用于构建弹性、可观察和可配置的云原生应用程序的堆栈。 .NET Aspire 附带了一组针对云原生开发增强的精选组件,默认情况下包括遥测、复原、配置和运行状况检查,这个项目来自几年前的实验性项目Tye。
.NET团队表示:“结合复杂而简单的本地开发人员体验,Aspire 可以在第 1 天起轻松发现、获取和配置云原生应用程序的基本依赖项。
在云原生的容器方面,.NET 8 通过简化应用程序的打包和使用默认的非 root 用户配置增强安全性来简化容器化。它还提供更小的映像大小以加快部署速度,并提供可选的Dirstroless Ubuntu 映像以增强安全性,以及多功能架构支持。
人工智能
随着生成式AI的到来,人工智能领域发生了翻天覆地的变化,从底层语言、运行时,到库的处理,到接口,到跨平台应用,对于 人工智能,.NET都有相对成熟的解决方案了。当下的这个生态位还是蓝海!.NET携带完整的工具和生态,杀进来,爽的不要不要的。用 .NET写整个的应用层代码,不需要写一行 C++ 代码,就可以架构整个完整的产品体系和服务体系。如果竞争对手选择的是其它技术架构,那么,你相对他,会有很强的生产力优势。.NET平台.NET 团队指出了展示模式和实践的各种示例和参考模板 可帮助开发人员入门,Semantic kernel 下个月发布正式版,目前是Beta6。
它们包括:
- 客户聊天机器人[7]
- 检索增强生成RAG[8]
- 使用 Azure AI 服务开发应用[8]
Blazor
Blazor 已经发展成为一个全栈 Web 开发框架,这要归功于由 .NET团队的 Steve Sanderson 领导的渲染改进,他是 Blazor 的创建者,最初称为“Blazor United”。它同时提供客户端 (Blazor WebAssembly) 和服务器端 (Blazor Server),能够根据条件提示切换设备。
ASP.NET 产品经理 Daniel Roth 今年早些时候是这么说:“在 .NET 8 中,我们正在扩展 Blazor 的功能,以便它能够处理所有 Web UI 需求,包括客户端和服务器端呈现。作为这项工作的一部分,我们正在将现有的 Blazor Server 和 Blazor WebAssembly 托管模型与新功能合并,例如无状态服务器端呈现、流式渲染、导航和表单处理的渐进式增强,以及使用 Blazor 或 Blazor WebAssembly 对每个组件进行交互的能力。
今天的公告总结了所有这些内容:“通过专注于优化页面加载时间、可伸缩性和提升用户体验的几项新增强功能,开发人员现在可以在同一应用中使用 Blazor Server 和 Blazor WebAssembly,在运行时自动将用户从服务器转移到客户端。由于新的基于“Jiterpreter”的运行时和新的内置组件,您的 .NET 代码在 WebAssembly 上的运行速度明显更快。作为增强 .NET 8 中整体身份验证、授权和标识管理[9]的一部分,Blazor 现在支持生成基于 Blazor 的完整标识 UI。
.NET MAUI
.NET团队表示,.NET多平台应用程序UI扩展了开发人员的工具箱,为使用.NET构建跨平台移动和桌面应用程序提供了全栈解决方案。 MAUI被称为 Xamarin.Forms 的“演变”,因为它增加了桌面支持,以提供跨 Android、iOS、macOS 和 Windows 的统一开发体验,帮助开发人员覆盖更广泛的受众。加上开源项目AvaloniaUI 和UNO的补充, .NET 可以覆盖所有平台的UI应用开发,特别是国内信创市场的桌面端.NET具有极强的竞争力
在 .NET 8 中,该框架通过对最新移动操作系统的额外支持扩展了其覆盖范围,并改进了性能、可靠性和开发人员体验。NativeAOT(实验性)现在支持针对类似 iOS 的平台。适用于 .NET MAUI 的新 Visual Studio Code 扩展[10]提供了开发跨平台 .NET 移动和桌面应用所需的工具。现在支持 Xcode 15 和 Android API 34,允许您面向最新版本的 iOS 和 Android。在性能、控件和 UI 元素以及特定于平台的行为方面[11]进行了大量质量改进,例如桌面交互增加了更好的点击处理、键盘侦听器等。
C#12
借助于C#12 ,你现在可以用简单而优雅的语法在任何类和结构中创建主要构造函数,不再需要样板代码来初始化字段和属性。使用简洁而富有表现力的语法创建数组、spans和其他集合类型。对 lambda 表达式中的参数使用新的默认值。不再需要重载或 null 检查来处理可选参数。您甚至可以使用 using alias 指令为任何类型设置别名,而不仅仅是命名类型!
C# 12 中的新增功能[12]”指南解释了版本 12 中的以下新功能:
-
主构造函数 - 在 Visual Studio 17.6 预览版 2 中引入。
-
Lambda 表达式中的可选参数 - 在 Visual Studio 17.5 预览版 2 中引入。
-
任何类型的别名 - 在 Visual Studio 17.6 预览版 3 中引入。
-
内联数组 - 在 Visual Studio 17.7 预览版 3 中引入。
-
集合表达式 - 在 Visual Studio 17.7 预览版 5 中引入。
-
拦截器 - 预览功能在 Visual Studio 17.7 预览版 3 中引入。
.NET 8.0 中有哪些新的变化?
1性能提升
.NET 8在整个堆栈中带来了数千项性能改进 。默认情况下会启用一种名为动态配置文件引导优化 (PGO) 的新代码生成器,它可以根据实际使用情况优化代码,并且可以将应用程序的性能提高高达 20%。现在支持的 AVX-512 指令集能够对 512 位数据向量执行并行操作,这意味着可以在更短的时间内处理更多的数据。原始类型(数字及其他类型)现在实现了新的可格式化和可解析接口,这使它们能够直接格式化和解析为 UTF-8,而无需任何转码开销。
2.NET Aspire
.NET Aspire 是一个用于使用 .NET 构建弹性、可观察和可配置的云原生应用程序的堆栈。它包括一组针对云原生而增强的精选组件,默认情况下包括遥测、弹性、配置和运行状况检查。结合复杂而简单的本地开发人员体验,.NET Aspire 可以在第 1 天和第 100 天轻松发现、获取和配置云原生应用程序的基本依赖项。
点击这里查看.NET Aspire的预览版本。
3.NET 8 容器增强功能 – 更安全、更紧凑、更高效
使用 .NET 比以往更轻松、更安全地使用容器打包应用程序。每个 .NET 映像都包含一个非 root 用户,从而通过单行配置启用更安全的容器。.NET SDK 工具无需 Dockerfile 即可发布容器映像,并且默认情况下是非 root 的。由于 .NET 基础映像更小,因此可以更快地部署容器化应用程序 - 包括我们映像的新实验变体,这些变体可为本机 AOT 提供真正最小的应用程序大小。选择使用新的 Chiseled Ubuntu 映像变体进行更多安全强化,以进一步减少攻击面。使用 Dockerfile 或 SDK 工具,为任何架构构建应用程序和容器映像。
4原生 AoT – 迈向更高密度可持续计算的旅程
无需等待 JIT(即时)编译器在运行时编译代码。无需部署JIT编译器和IL代码。AOT 应用程序仅部署应用程序所需的代码。应用程序现在可以在不允许使用 JIT 编译器的受限环境中运行。
5人工智能 – 将 AI 融入您的 .NET 应用程序
生成式人工智能和大型语言模型正在改变人工智能领域,使开发人员能够在其应用程序中创建独特的人工智能体验。.NET 8 可以通过 .NET SDK 中一流的开箱即用 AI 功能以及与多种工具的无缝集成来轻松利用 AI。
.NET 8 为该 库带来了多项增强功能,以提高其与生成式 AI 工作负载的兼容性,例如集成 Tensor Primitives。随着人工智能应用程序的兴起,新的工具和 SDK 出现了。我们与众多内部和外部合作伙伴合作,例如Azure OpenAI、Azure Cognitive Search、Milvus、Qdrant和Microsoft Teams,以确保 .NET 开发人员可以通过各自的 SDK 轻松访问各种 AI 模型、服务和平台。此外,开源语义内核SDK 简化了这些 AI 组件与新的和现有应用程序的集成,以帮助您提供创新的用户体验。System.Numerics
现在提供各种示例和参考模板,展示模式和实践,以便开发人员轻松入门:
6Blazor – 使用 .NET 构建全栈 Web 应用程序
.NET 8 中的 Blazor 可以同时使用服务器和客户端来处理您的所有 Web UI 需求。这是全栈 Web UI!通过专注于优化页面加载时间、可扩展性和提升用户体验的多项新增强功能,开发人员现在可以在同一应用程序中使用Blazor Server 和 Blazor WebAssembly,在运行时自动将用户从服务器转移到客户端。得益于新的基于“Jiterpreter”的运行时和新的内置组件,您的 .NET 代码在 WebAssembly 上的运行速度显着加快。作为增强.NET 8 中整体身份验证、授权和身份管理的一部分,Blazor 现在支持生成完整的基于 Blazor 的身份 UI。
7.NET MAUI – 提升性能、可靠性和开发人员体验
.NET MAUI 提供单一项目系统和单一代码库来构建 WinUI、Mac Catalyst、iOS 和 Android 应用程序。本机 AOT(实验性)现在支持针对类似 iOS 的平台。适用于 .NET MAUI 的新 Visual Studio Code 扩展为您提供了开发跨平台 .NET 移动和桌面应用程序所需的工具。现在支持 Xcode 15 和 Android API 34,允许您瞄准最新版本的 iOS 和 Android。在性能、控件和 UI 元素以及特定于平台的行为方面进行了大量的质量改进,例如桌面交互添加了更好的点击处理、键盘侦听器等。
8 C# 12 功能 – 简化语法以提高开发人员的工作效率
C# 12 让您的编码体验更加高效和愉快。现在,您可以使用简单而优雅的语法在任何类和结构中创建主构造函数。不再需要样板代码来初始化您的字段和属性。使用简洁且富有表现力的语法创建数组、跨度和其他集合类型时会感到高兴。对 lambda 表达式中的参数使用新的默认值。不再需要重载或空检查来处理可选参数。您甚至可以使用usingalias 指令为任何类型添加别名,而不仅仅是命名类型!
8.1集合表达式
在 C# 12 之前,创建集合需要针对不同场景使用不同的语法。初始化所需的与or不同的语法。以下是创建集合的几种方法:List<int>int[]Span<int>
int[] x1 = new int[] { 1, 2, 3, 4 };
int[] x2 = Array.Empty<int>();
WriteByteArray(new[] { (byte)1, (byte)2, (byte)3 });
List<int> x4 = new() { 1, 2, 3, 4 };
Span<DateTime> dates = stackalloc DateTime[] { GetDate(0), GetDate(1) };
WriteByteSpan(stackalloc[] { (byte)1, (byte)2, (byte)3 });
8.2任何类或结构上的主构造函数
C# 12 扩展了主构造函数以适用于所有类和结构,而不仅仅是记录。主构造函数允许在声明类时定义构造函数参数:
public class BankAccount(string accountID, string owner)
{
public string AccountID { get; } = accountID;
public string Owner { get; } = owner;
public override string ToString() => $"Account ID: {AccountID}, Owner: {Owner}";
}
主构造函数参数最常见的用途是:
- 作为 base() 构造函数调用的参数。
- 初始化成员字段或属性。
- 在实例成员中引用构造函数参数。
- 删除依赖注入中的样板。
8.3别名任意类型
别名类型是从代码中删除复杂类型签名的便捷方法。using从 C# 12 开始,其他类型在别名指令中有效。例如,这些别名在早期版本的 C# 中无效:
using intArray = int[]; // Array types.
using Point = (int x, int y); // Tuple type
using unsafe ArrayPtr = int*; // Pointer type (requires "unsafe")
8.4默认 lambda 参数
从 C# 12 开始,您可以在 lambda 表达式中声明默认参数:
var IncrementBy = (int source, int increment = 1) => source + increment;
Console.WriteLine(IncrementBy(5)); // 6
Console.WriteLine(IncrementBy(5, 2)); // 7
8.5内联数组
运行时团队和其他库作者使用内联数组来提高应用的性能。 内联数组使开发人员能够创建固定大小的 struct 类型数组。 具有内联缓冲区的结构应提供类似于不安全的固定大小缓冲区的性能特征。 你可能不会声明自己的内联数组,但当它们从运行时 API 作为 System.Span<T> 或 System.ReadOnlySpan<T> 对象公开时,你将透明地使用这些数组。
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
它们的用法与任何其他数组类似:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
buffer[i] = i;
}
foreach (var i in buffer)
{
Console.WriteLine(i);
}
区别在于编译器可以利用有关内联数组的已知信息。 你可能会像使用任何其他数组一样使用内联数组。 有关如何声明内联数组的详细信息,请参阅有关 struct 类型的语言参考。
9.反射改进
.NET 5 中引入了函数指针,但当时未添加对反射的相应支持。 对函数指针使用 typeof 或反射时(例如分别使用 typeof(delegate*<void>()) 或 FieldInfo.FieldType),返回了 IntPtr。 从 .NET 8 开始,将改为返回 System.Type 对象。 此类型提供对函数指针元数据的访问,包括调用约定、返回类型和参数。
新功能目前仅在 CoreCLR 运行时和 MetadataLoadContext 中实现。已将新的 API 添加到 System.Type(例如 IsFunctionPointer)以及 System.Reflection.PropertyInfo、System.Reflection.FieldInfo 和 System.Reflection.ParameterInfo。 以下代码演示如何使用一些新 API 进行反射。
// Sample class that contains a function pointer field.
public unsafe class UClass
{
public delegate* unmanaged[Cdecl, SuppressGCTransition]<in int, void> _fp;
}
// ...
FieldInfo fieldInfo = typeof(UClass).GetField(nameof(UClass._fp));
// Obtain the function pointer type from a field.
Type fpType = fieldInfo.FieldType;
// New methods to determine if a type is a function pointer.
Console.WriteLine($"IsFunctionPointer: {fpType.IsFunctionPointer}");
Console.WriteLine($"IsUnmanagedFunctionPointer: {fpType.IsUnmanagedFunctionPointer}");
// New methods to obtain the return and parameter types.
Console.WriteLine($"Return type: {fpType.GetFunctionPointerReturnType()}");
foreach (Type parameterType in fpType.GetFunctionPointerParameterTypes())
{
Console.WriteLine($"Parameter type: {parameterType}");
}
// Access to custom modifiers and calling conventions requires a "modified type".
Type modifiedType = fieldInfo.GetModifiedFieldType();
// A modified type forwards most members to its underlying type.
Type normalType = modifiedType.UnderlyingSystemType;
// New method to obtain the calling conventions.
foreach (Type callConv in modifiedType.GetFunctionPointerCallingConventions())
{
Console.WriteLine($"Calling convention: {callConv}");
}
// New method to obtain the custom modifiers.
foreach (Type modreq in modifiedType.GetFunctionPointerParameterTypes()[0].GetRequiredCustomModifiers())
{
Console.WriteLine($"Required modifier for first parameter: {modreq}");
}
输出:
IsFunctionPointer: True
IsUnmanagedFunctionPointer: True
Return type: System.Void
Parameter type: System.Int32&
Calling convention: System.Runtime.CompilerServices.CallConvSuppressGCTransition
Calling convention: System.Runtime.CompilerServices.CallConvCdecl
Required modifier for first parameter: System.Runtime.InteropServices.InAttribute
10.配置绑定源生成器
.NET 8 引入了一个源生成器,用于在 ASP.NET Core 中提供 AOT 和适合剪裁的配置。 该生成器是现有的基于反射的实现的替代方法。
源生成器探测 Configure(TOptions)、Bind 和 Get 调用来从中检索类型信息。 在项目中启用生成器后,编译器将隐式选择生成的方法,而非预先存在的基于反射的框架实现。
无需更改源代码即可使用生成器。 AOT Web 应用中默认启用该生成器。 对于其他项目类型,源生成器默认关闭,但你可通过在项目文件中将 EnableConfigurationBindingGenerator 属性设置为 true 来选择使用它:
<PropertyGroup>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
以下代码演示了调用绑定器的示例:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
IConfigurationSection section = builder.Configuration.GetSection("MyOptions");
// !! Configure call - to be replaced with source-gen'd implementation
builder.Services.Configure<MyOptions>(section);
// !! Get call - to be replaced with source-gen'd implementation
MyOptions options0 = section.Get<MyOptions>();
// !! Bind call - to be replaced with source-gen'd implementation
MyOptions options1 = new MyOptions();
section.Bind(options1);
WebApplication app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
public class MyOptions
{
public int A { get; set; }
public string S { get; set; }
public byte[] Data { get; set; }
public Dictionary<string, string> Values { get; set; }
public List<MyClass> Values2 { get; set; }
}
public class MyClass
{
public int SomethingElse { get; set; }
}
11.针对 Android 应用的 AOT 编译
为了减小应用大小,面向 Android 的 .NET 和 .NET MAUI 应用在发布模式下构建时使用分析的预先 (AOT) 编译模式。 与常规 AOT 编译相比,分析的 AOT 编译所影响的方法更少。 .NET 8 引入了 <AndroidStripILAfterAOT> 属性,你可使用它进一步对 Android 应用进行 AOT 编译,从而更进一步减少应用大小。
<PropertyGroup>
<AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
</PropertyGroup>
默认情况下,将 AndroidStripILAfterAOT 设置为 true 会替代默认的 AndroidEnableProfiledAot 设置,从而允许剪裁已 AOT 编译的(几乎)所有方法。 还可通过将两个属性都显式设置为 true 来结合使用分析的 AOT 和 IL 条带化:
<PropertyGroup>
<AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>
12.代码分析
.NET 8 包括几个新的代码分析器和修复程序,可帮助验证是否正确且高效地使用 .NET 库 API。 下表总结了新的分析器。
规则 ID | 类别 | 说明 |
---|---|---|
CA1856 | 性能 | 未在参数上正确应用 ConstantExpectedAttribute 属性时触发。 |
CA1857 | 性能 | 当参数使用 ConstantExpectedAttribute 添加批注但提供的参数不是常量时触发。 |
CA1858 | 性能 | 若要确定字符串是否以给定前缀开头,最好调用 String.StartsWith,而不是调用 String.IndexOf,然后将结果与零进行比较。 |
CA1859 | 性能 | 此规则建议尽可能将特定局部变量、字段、属性、方法参数和方法返回类型从接口或抽象类型升级到具体类型。 使用具体类型可生成更高质量的代码。 |
CA1860 | 性能 | 若要确定集合类型是否具有任何元素,最好使用 Length、Count 或 IsEmpty,而不是调用 Enumerable.Any。 |
CA1861 | 性能 | 重复调用时,不会重复使用作为参数传递的常量数组,这意味着每次都会创建一个新数组。 若要提高性能,请考虑将数组提取到静态只读字段。 |
CA1865-CA1867 | 性能 | 对于单字符串,char 重载的性能更好。 |
CA2021 | 可靠性 | Enumerable.Cast(IEnumerable) 和 Enumerable.OfType(IEnumerable) 需要兼容的类型才能正常运行。 泛型类型不支持扩大转换和用户定义的转换。 |
CA1510-CA1513 | 可维护性 | 在构造新的异常实例方面,引发帮助程序比 if 块更简单、更高效。 这四个分析器是为以下例外情况创建的:ArgumentNullException、ArgumentException、ArgumentOutOfRangeException 和 ObjectDisposedException。 |
13.Core .NET 库
13.1时间抽象
新的 TimeProvider 类和 ITimer 接口添加了时间抽象功能,让你可以在测试方案中模拟时间。 此外,还可以使用时间抽象,通过 Task.Delay 和 Task.WaitAsync 来模拟依赖于时间进度的 Task 操作。 时间抽象支持以下基本时间操作:
- 检索本地和 UTC 时间
- 获取用于测量性能的时间戳
- 创建计时器
以下代码片段演示了一些使用情况示例。
// Get system time.
DateTimeOffset utcNow = TimeProvider.System.GetUtcNow();
DateTimeOffset localNow = TimeProvider.System.GetLocalNow();
// Create a time provider that works with a
// time zone that's different than the local time zone.
private class ZonedTimeProvider : TimeProvider
{
private TimeZoneInfo _zoneInfo;
public ZonedTimeProvider(TimeZoneInfo zoneInfo) : base()
{
_zoneInfo = zoneInfo ?? TimeZoneInfo.Local;
}
public override TimeZoneInfo LocalTimeZone => _zoneInfo;
public static TimeProvider FromLocalTimeZone(TimeZoneInfo zoneInfo) =>
new ZonedTimeProvider(zoneInfo);
}
// Create a timer using a time provider.
ITimer timer = timeProvider.CreateTimer(callBack, state, delay, Timeout.InfiniteTimeSpan);
// Measure a period using the system time provider.
long providerTimestamp1 = TimeProvider.System.GetTimestamp();
long providerTimestamp2 = TimeProvider.System.GetTimestamp();
var period = GetElapsedTime(providerTimestamp1, providerTimestamp2);
13.2UTF8 改进
如果要启用将类型的类似字符串的表示形式写出到目标范围,请在类型上实现新的 IUtf8SpanFormattable 接口。 此新接口与 ISpanFormattable 密切相关,但面向 UTF8 和 Span<byte>,而不是 UTF16 和 Span<char>。
IUtf8SpanFormattable 已在所有基元类型(以及其他)上实现,无论是面向 string、Span<char> 还是 Span<byte>,其共享逻辑完全一致。 它完全支持所有格式(包括新的“B”二进制说明符)和所有区域性。 这意味着现在可以从 Byte、Complex、Char、DateOnly、DateTime、DateTimeOffset、Decimal、Double、Guid、Half、IPAddress、IPNetwork、Int16、Int32、Int64、Int128、IntPtr、NFloat、SByte、Single、Rune、TimeOnly、TimeSpan、UInt16、UInt32、UInt64、UInt128、UIntPtr 和 Version 直接格式化为 UTF8。
新的 Utf8.TryWrite 方法向现有 MemoryExtensions.TryWrite 方法(基于 UTF16)提供基于 UTF8 的对应方法。 可以使用内插字符串语法将复杂表达式直接格式化为 UTF8 字节范围,例如:
static bool FormatHexVersion(
short major,
short minor,
short build,
short revision,
Span<byte> utf8Bytes,
out int bytesWritten) =>
Utf8.TryWrite(
utf8Bytes,
CultureInfo.InvariantCulture,
$"{major:X4}.{minor:X4}.{build:X4}.{revision:X4}",
out bytesWritten);
13.3加密
.NET 8 添加了对 SHA-3 哈希基元的支持。 (目前,具有 OpenSSL 1.1.1 或更高版本和 Windows 11 Build 25324 或更高版本的 Linux 支持 SHA-3。)可在其中使用 SHA-2 的 API 现在提供对 SHA-3 的补充。 对于哈希,这包括 SHA3_256、SHA3_384 和 SHA3_512;对于 HMAC,这包括 HMACSHA3_256、HMACSHA3_384 和 HMACSHA3_512;对于其中可配置算法的哈希,这包括 HashAlgorithmName.SHA3_256、HashAlgorithmName.SHA3_384 和 HashAlgorithmName.SHA3_512;对于 RSA OAEP 加密,这包括 RSAEncryptionPadding.OaepSHA3_256、RSAEncryptionPadding.OaepSHA3_384 和 RSAEncryptionPadding.OaepSHA3_512。
以下示例演示如何使用 API(包括 SHA3_256.IsSupported 属性)来确定平台是否支持 SHA-3。
// Hashing example
if (SHA3_256.IsSupported)
{
byte[] hash = SHA3_256.HashData(dataToHash);
}
else
{
// ...
}
// Signing example
if (SHA3_256.IsSupported)
{
using ECDsa ec = ECDsa.Create(ECCurve.NamedCurves.nistP256);
byte[] signature = ec.SignData(dataToBeSigned, HashAlgorithmName.SHA3_256);
}
else
{
// ...
}
13.4基于流的 ZipFile 方法
.NET 8 包含 ZipFile.CreateFromDirectory 的新重载,通过它可以收集目录中包含的所有文件并压缩这些文件,然后将生成的 zip 文件存储到提供的流中。 同样,通过新的 ZipFile.ExtractToDirectory 重载,可提供包含压缩文件的流,并将其内容提取到文件系统中。 下面是新的重载:
namespace System.IO.Compression;
public static partial class ZipFile
{
public static void CreateFromDirectory(string sourceDirectoryName, Stream destination);
public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, CompressionLevel compressionLevel, bool includeBaseDirectory);
public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, CompressionLevel compressionLevel, bool includeBaseDirectory, Encoding? entryNameEncoding);
public static void ExtractToDirectory(Stream source, string destinationDirectoryName) { }
public static void ExtractToDirectory(Stream source, string destinationDirectoryName, bool overwriteFiles) { }
public static void ExtractToDirectory(Stream source, string destinationDirectoryName, Encoding? entryNameEncoding) { }
public static void ExtractToDirectory(Stream source, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles) { }
}
总结
围绕 .NET 8 有一大堆新特性和功能, Microsoft 还宣布 Visual Studio 2022 17.8 已正式发布。该公司还指出其 VS Code 和 C# 开发工具包可以帮助新手入门。Microsoft表示,另一种入门方法是使用SDK中新的.NET的GitHub Codespaces模板[13]。
今天的公告帖子还包括指向更多资源的链接,这些资源有助于充实 .NET 8 中跨 ASP.NET Core、Entity Framework Core、NuGet、.NET 运行时、.NET SDK、WPF、ARM64、调试等的新增功能。
相关链接:
- [1].NET Conf 2023: https://www.dotnetconf.net/
- [2].NET 8:https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0
- [3]Survey: Native AOT [results]:https://github.com/dotnet/runtime/issues/41522
- [4].NET8公告博客:https://devblogs.microsoft.com/dotnet/announcing-dotnet-8/
- [5].NET 7 速度超快, .NET 8 更快:https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/
- [6]TechEmpower 22轮Web框架 性能评测:.NET 8 战绩斐然:https://www.cnblogs.com/shanyou/p/17828353.html
- [7]客户聊天机器人:https://github.com/dotnet-architecture/eShop
- [8]检索增强生成RAG: https://github.com/Azure-Samples/azure-search-openai-demo-csharp
- [9]使用 Azure AI 服务开发应用: https://devblogs.microsoft.com/dotnet/demystifying-retrieval-augmented-generation-with-dotnet/
- [10]Visual Studio Code 扩展: https://aka.ms/maui-devkit-blog
- [11]行为方面性能改进: https://devblogs.microsoft.com/dotnet/dotnet-8-performance-improvements-in-dotnet-maui
- [12]C# 12 中的新增功能: https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-12
- [13]SDK中新的.NET的GitHub Codespaces模板: https://github.com/codespaces