What are the new changes in. NET 8.0?

What are the new changes in. NET 8.0?

NET 8 brings thousands of performance improvements across the stack

最后更新 11/17/2023 4:03 PM
葡萄城技术团队
预计阅读 20 分钟
分类
.NET
标签
.NET C# tech refresh

**1. Performance improvement **

.NET 8 在整个堆栈带来了数千项性能改进 。默认情况下会启用一种名为动态配置文件引导优化 (PGO) 的新代码生成器,它可以根据实际使用情况优化代码,并且可以将应用程序的性能提高高达 20%。现在支持的 AVX-512 指令集能够对 512 位数据向量执行并行操作,这意味着可以在更短的时间内处理更多的数据。原始类型(数字及其他类型)现在实现了新的可格式化和可解析接口,这使它们能够直接格式化和解析为 UTF-8,而无需任何转码开销。 img

2. NET Aspire

NET Aspire is a stack for building resilient, observable, and configurable cloud-native applications using. NET. It includes a select set of components that are enhanced for cloud-native, including telemetry, elasticity, configuration and health checks by default. Combined with a complex and simple local developer experience,. NET Aspire can easily discover, acquire, and configure basic dependencies for cloud-native applications on day 1 and 100.

Click here to view a preview version of. NET Aspire. (Webmaster's note: There is no link here, let's see how to find and supplement later) img

**3. NET 8 Container Enhancements-Safer, more compact, and more efficient **

使用 .NET 比以往更轻松、更安全地使用容器打包应用程序。每个 .NET 映像都包含一个非 root 用户,从而通过单行配置启用更安全的容器。.NET SDK 工具无需 Dockerfile 即可发布容器映像,并且默认情况下是非 root 的。由于 .NET 基础映像更小,因此可以更快地部署容器化应用程序 - 包括我们映像的新实验变体,这些变体可为本机 AOT 提供真正最小的应用程序大小。选择使用新的 Chiseled Ubuntu 映像变体进行更多安全强化,以进一步减少攻击面。使用 Dockerfile 或 SDK 工具,为任何架构构建应用程序和容器映像。

img

**4. Native AoT-A journey towards higher density and sustainable computing **

There is no need to wait for the JIT (just-in-time) compiler to compile your code at runtime. There is no need to deploy JIT compilers and IL code. AOT applications deploy only the code required by the application. Applications can now run in restricted environments that do not allow the use of JIT compilers.

img

**5. Artificial Intelligence-Integrate AI into your. NET applications **

生成式人工智能和大型语言模型正在改变人工智能领域,使开发人员能够在其应用程序中创建独特的人工智能体验。.NET 8 可以通过 .NET SDK 中一流的开箱即用 AI 功能以及与多种工具的无缝集成来轻松利用 AI。

NET 8 brings multiple enhancements to the library to improve its compatibility with generative AI workloads, such as integrating Tensor Primitives. With the rise of artificial intelligence applications, new tools and SDKs have emerged. We work with numerous internal and external partners, such as Azure OpenAI, Azure Cognitive Search, Milvus, Qdrant, and Microsoft Teams, to ensure that. NET developers can easily access various AI models, services, and platforms through their respective SDKs. In addition, the open source Semantic Kernel System.Numerics SDK simplifies the integration of these AI components with new and existing applications to help you provide innovative user experiences.

Various examples and reference templates are now available to demonstrate patterns and practices so that developers can easily get started:

img

**6. Blazor-Building full-stack Web applications using. NET **

Blazor in. NET 8 can use both a server and a client to handle all of your Web UI needs. This is a full-stack Web UI! With multiple new enhancements focused on optimizing page load times, scalability and improving user experience, developers can now use Blazor Server and Blazor WebAssembly in the same application, automatically transferring users from server to client at runtime. Thanks to the new "Jiterpreter"-based runtime and new built-in components, your. NET code runs significantly faster on WebAssembly. As part of enhancing overall authentication, authorization, and identity management in. NET 8, Blazor now supports the generation of a complete Blazor-based identity UI.

img

**7. NET MAUI-Improve performance, reliability and developer experience **

NET MAUI provides a single project system and a single code base to build WinUI, Mac Catalyst, iOS and Android applications. Native AOT (Experimental) is now supported for platforms like iOS. The new Visual Studio Code extension for. NET MAUI gives you the tools you need to develop cross-platform. NET mobile and desktop applications. Xcode 15 and Android API 34 are now supported, allowing you to target the latest versions of iOS and Android. There have been a number of quality improvements in performance, controls and UI elements, and platform-specific behavior, such as the addition of better click processing, keyboard listeners, etc. to desktop interactions.

img

**8. C#12 Features-Simplify syntax to improve developer productivity **

C#12 makes your coding experience more efficient and enjoyable. You can now create a main constructor in any class and structure using simple and elegant syntax. Boilerplate code is no longer needed to initialize your fields and properties. Enjoy creating arrays, spans, and other collection types using concise and expressive syntax. Use new default values for parameters in lambda expressions. Overloads or null checks are no longer needed to handle optional parameters. You can even use the using alias directive to add aliases to any type, not just named types!

**8.1. Collective expression **

在 C# 12 之前,创建集合需要针对不同场景使用不同的语法。初始化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. Main constructor on any class or structure **

C#12 extends the main constructor to apply to all classes and constructs, not just records. The main constructor allows you to define constructor parameters when declaring a class:

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}";
}

The most common uses for main constructor parameters are:

  • As an argument to the base() constructor call.
  • Initialize a member field or property.
  • Reference constructor parameters in instance members.
  • Remove the template from dependency injection.

**8.3. Alias of any type **

Alias types are a convenient way to remove complex type signatures from code. Using starts with C#12, and other types are valid in alias instructions. For example, these aliases are not valid in earlier versions of C#:

using intArray = int[]; // Array types.
using Point = (int x, int y);  // Tuple type
using unsafe ArrayPtr = int*;  // Pointer type (requires "unsafe")

**8.4. Default lambda parameter **

Starting from C#12, you can declare default parameters in lambda expressions:

var IncrementBy = (int source, int increment = 1) => source + increment;

Console.WriteLine(IncrementBy(5)); // 6
Console.WriteLine(IncrementBy(5, 2)); // 7

**8.5. Inline array **

运行时团队和其他库作者使用内联数组来提高应用的性能。 内联数组使开发人员能够创建固定大小的 struct 类型数组。 具有内联缓冲区的结构应提供类似于不安全的固定大小缓冲区的性能特征。 你可能不会声明自己的内联数组,但当它们从运行时 API 作为 System.SpanSystem.ReadOnlySpan 对象公开时,你将透明地使用这些数组。

[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
    private int _element0;
}

Their usage is similar to any other array:

var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
    buffer[i] = i;
}

foreach (var i in buffer)
{
    Console.WriteLine(i);
}

区别在于编译器可以利用有关内联数组的已知信息。 你可能会像使用任何其他数组一样使用内联数组。 有关如何声明内联数组的详细信息,请参阅有关 struct 类型的语言参考。

**9. Reflection improvement **

.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}");
}

Output:

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. Configure Binding Source Generator **

NET 8 introduces a source generator to provide AOT and tailor-appropriate configurations in ASP.NET Core. This generator is an alternative to existing reflection-based implementations.

源生成器探测 Configure(TOptions)、Bind 和 Get 调用来从中检索类型信息。 在项目中启用生成器后,编译器将隐式选择生成的方法,而非预先存在的基于反射的框架实现。

You can use the generator without changing the source code. This generator is enabled by default in AOT Web applications. For other project types, the source generator is turned off by default, but you can choose to use it by setting the EnableConfigurationBindingGenerator property to true in the project file:

<PropertyGroup>
    <EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>

The following code demonstrates an example of calling a binder:

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. AOT compilation for Android apps **

为了减小应用大小,面向 Android 的 .NET 和 .NET MAUI 应用在发布模式下构建时使用分析的预先 (AOT) 编译模式。 与常规 AOT 编译相比,分析的 AOT 编译所影响的方法更少。 .NET 8 引入了 <AndroidStripILAfterAOT> 属性,你可使用它进一步对 Android 应用进行 AOT 编译,从而更进一步减少应用大小。

<PropertyGroup>
  <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
</PropertyGroup>

By default, setting AndroidStripILAfterAOT to true overrides the default AndroidEnableProfiledAot setting, allowing clipping of (almost) all methods that have been AOT-compiled. You can also use analytical AOT and IL banding in conjunction with analysis by explicitly setting both attributes to true:

<PropertyGroup>
  <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
  <AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>

**12. Code Analysis **

NET 8 includes several new code analyzers and fixes that help verify correct and efficient use of the. NET library API. The following table summarizes the new analyzers.

rule ID category description
CA1856 performance 未在参数上正确应用 ConstantExpectedAttribute 属性时触发。
CA1857 performance 当参数使用 ConstantExpectedAttribute 添加批注但提供的参数不是常量时触发。
CA1858 performance 若要确定字符串是否以给定前缀开头,最好调用 String.StartsWith,而不是调用 String.IndexOf,然后将结果与零进行比较。
CA1859 performance This rule recommends upgrading specific local variables, fields, properties, method parameters, and method return types from interface or abstract types to concrete types whenever possible. Using specific types generates higher-quality code.
CA1860 performance 若要确定集合类型是否具有任何元素,最好使用 Length、Count 或 IsEmpty,而不是调用 Enumerable.Any
CA1861 performance When called repeatedly, the array of constants passed as arguments is not reused, which means a new array is created every time. To improve performance, consider extracting arrays into static read-only fields.
CA1865-CA1867 performance For single strings, char overloads perform better.
CA2021 reliability Enumerable.Cast(IEnumerable)Enumerable.OfType(IEnumerable) 需要兼容的类型才能正常运行。 泛型类型不支持扩大转换和用户定义的转换。
CA1510-CA1513 the maintainability 在构造新的异常实例方面,引发帮助程序比 if 块更简单、更高效。 这四个分析器是为以下例外情况创建的:ArgumentNullExceptionArgumentExceptionArgumentOutOfRangeExceptionObjectDisposedException

**13. . NET Core Library **

**13.1. Time abstract **

新的 TimeProvider 类和 ITimer 接口添加了时间抽象功能,让你可以在测试方案中模拟时间。 此外,还可以使用时间抽象,通过 Task.DelayTask.WaitAsync 来模拟依赖于时间进度的 Task 操作。 时间抽象支持以下基本时间操作:

  • Retrieves local and UTC times
  • Get a timestamp used to measure performance
  • create a timer

The following code snippets demonstrate some usage examples.

// 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.2. UTF8 improvements **

如果要启用将类型的类似字符串的表示形式写出到目标范围,请在类型上实现新的 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. Encryption **

NET 8 adds support for SHA-3 hash primitives. (Currently, SHA-3 is supported on Linux with OpenSSL 1.1.1 or higher and Windows 11 Build 25324 or higher.) APIs in which SHA-2 can be used now provide supplements to SHA-3. For hashes, this includes SHA3_256, SHA3_384, and SHA3_512; for HMAC, this includes HMACSHA3_256, HMACSHA3_384, and HMACSHA3_512; for hashes in which algorithms can be configured, this includes HashAlgorithm Name.SHA3_256, HashAlgorithm Name.SHA3_384, and HashAlgorithm Name.SHA3_512; For RSA OAEP encryption, this includes RSAEncryptionPadding.OaepSHA3_256, RSAEncryptionPadding.OaepSHA3_384, and RSAEncryptionPadding.OaepSHA3_512.

The following example demonstrates how to use the API (including the SHA3_256.IsSupported attribute) to determine whether the platform supports 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. Stream-based ZipFile method **

.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) { }
}

GrapeCity Documents for Excel (referred to as GcExcel) is a server-side high-performance table component based on the. NET and. NET Core platforms without relying on Office, NPOI or third-party applications. Display table data on the front end, create, load, edit, print, and import/export Excel documents in batches on the server, providing applications you develop with data synchronization of front and back ends of online documents, online filling, and batch export and printing on the server.

ActiveReports是一款专注于 .NET 和 .NET Core 平台的报表控件。通过拖拽式报表设计器,可以快速地设计 Excel 表格、Word 文档、图表、数据过滤、数据钻取、精准套打等类型报表,全面满足 WinForm、ASP.NET、ASP.NET MVC、WPF 平台中各种报表的开发需要。同时,通过丰富的 API 可以灵活的实现报表创建、加载和运行时的个性化自定义需求。

Wyn 商业智能是基于葡萄城 20 多年数据分析技术积累打造的全新一代嵌入式 BI 产品,旨在提供可与应用系统深度集成的数据分析功能,能够与企业现有业务系统 OA, ERP,MES,CRM 等应用系统深度集成,整合、分析多个业务系统的数据,自助式分析业务数据、实时分析决策,全面提升企业竞争力。

Spread .NET是一个功能、布局与 Excel 高度类似的 .NET 表格控件,可全面满足 WinForm、ASP.NET、XAML 和 WinRT 等平台下表格数据处理、数据可视化开发需求。Spread .NET 支持 462 种 Excel 公式,提供可嵌入系统的类 Excel 设计器和全面开放的 API,为 .NET 开发人员构建企业级表格应用程序提供更加专业的选择。

References:

https://learn.microsoft.com/zh-cn/dotnet/core/whats-new/dotnet-8#networking

** Extended links: **

如何使用 Blazor 框架在前端浏览器中导入/导出 Excel XLSX

如何在.NET 电子表格应用程序中创建流程图

如何将实时数据显示在前端电子表格中


本文是由葡萄城技术开发团队发布,转载请注明出处:葡萄城官网

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 4/22/2026

Support for. NET by operating system versions (250707 update)

Use virtual machines and test machines to test the support of each version of the operating system for. NET. After installing the operating system, it is passed by measuring the corresponding running time of the installation and being able to run the Stardust Agent.

继续阅读
同分类 / 同标签 2/7/2026

Summary of experience in using AOT

From the very beginning of project creation, you should develop a good habit of conducting AOT release testing in a timely manner whenever new features are added or newer syntax is used.

继续阅读