.NET 7预览版更新功能介绍及使用方法

565 阅读9分钟

今天我们发布了.NET 7预览版。这是.NET 7的最后一个预览版,下一个版本将是我们的第一个候选版本(RC)。.NET大会2022年的日期已经公布!加入我们吧,2022年11月8日至10日,庆祝.NET 7的发布!

Visual Studio 2022 17.3也于今天发布,对.NET多平台应用程序用户界面(MAUI)的GA支持。阅读.NET MAUI公告并收听.NET会议。专注于MAUI,现在正在现场直播!

.NET 7预览版包括对System.LINQ、Unix文件权限、低级结构、p/Invoke源生成、代码生成和websockets的改进。

你可以下载.NET 7预览版7,用于Windows、macOS和Linux:

.NET 7预览版已经用Visual Studio 17.4 Preview 1进行了测试。如果你想用Visual Studio家族产品尝试.NET 7,我们建议你使用预览通道构建。如果你是在macOS上,我们建议使用最新的Visual Studio 2022 for Mac预览版。现在,让我们进入这个版本中的一些最新更新。

简化排序与System.LINQ

dotnet/runtime#67194

System.Linq 现在有了 和 方法,用于根据 对 进行排序。Order OrderDescending T IEnumerable

IQueryable 现在也支持这个。

注意:这一变化并没有System.Linq.Expressions

使用方法

以前,你必须通过引用自己的值来调用OrderBy/OrderByDescending

var data = new[] { 2, 1, 3 };
var sorted = data.OrderBy(static e => e);
var sortedDesc = data.OrderByDescending(static e => e);

现在,你可以写:

var data = new[] { 2, 1, 3 };
var sorted = data.Order();
var sortedDesc = data.OrderDescending();

支持Unix文件模式

以前,.NET没有对获取和设置Unix文件权限的内置支持,这些权限控制哪些用户可以读取、写入和执行文件和目录。P/手动调用系统调用并不容易,因为有些系统调用在不同的发行版上有不同的暴露方式。例如,在Ubuntu上,你可能需要向__xstat ,在RedHat上向stat ,以此类推。这使得一流的.NET API非常重要。

在预览7中,我们引入了一个新的枚举:

public enum UnixFileMode
{
    None,
    OtherExecute, OtherWrite, OtherRead,
    GroupExecute, GroupWrite, GroupRead,
    UserExecute, UserWrite, UserRead,
     ...
}

和APIFile.GetUnixFileModeFile.SetUnixFileMode ,以获取和设置路径或句柄(文件描述符)的文件模式。以及在FileInfoDirectoryInfo 上的一个新的属性,名为UnixFileMode

还有一个新的Directory.CreateDirectory 的重载和一个新的FileStreamOptions 的属性,允许你一次性创建一个具有特定模式的目录或文件。注意,当你使用这些时,umask 仍然被应用,就像你在shell中创建目录或文件时一样。

使用方法

// Create a new directory with specific permissions
Directory.CreateDirectory("myDirectory", UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);

// Create a new file with specific permissions
FileStreamOptions options = new()
{
    Access = FileAccess.Write,
    Mode = FileMode.Create,
    UnixCreateMode =  UnixFileMode.UserRead | UnixFileMode.UserWrite,
};
using FileStream myFile = new FileStream("myFile", options);

// Get the mode of an existing file
UnixFileMode mode = File.GetUnixFileMode("myFile");

// Set the mode of an existing file
File.SetUnixFileMode("myFile", UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);

查看所有新的Unix文件模式API

低级别的struct 改进:ref 字段支持

.NET 7运行机制现在完全支持ByRefLike类型中的ref 字段(即ref struct )。在这个被要求的功能背后有大量的语言设计,用户可以阅读:低级结构改进。有了这个功能,以前需要在运行时专门处理的类型(例如:Span<T>ReadOnlySpan<T> ),现在可以在C#中完全实现。

LibraryImport P/Invoke源生成器

dotnet/runtime#60595

LibraryImport 源生成器现在可以以支持的方式提供给所有用户。经过18个多月的努力,这个源码生成器被设计成可以直接替代大多数DllImport ,包括在运行时产品和用户代码中的使用。.NET库已经全部采用了LibraryImport ,并且从.NET 7 Preview 1开始就使用了源码生成的marshalling代码。

源码生成器与.NET 7 TFM一起发货,并可随时供人使用。为了获得源码生成器的好处,用LibraryImport 替换DllImport 的使用。有一些分析器和修复器可以帮助完成这个过程。

使用方法

使用前

public static class Native
{
    [DllImport(nameof(Native), CharSet = CharSet.Unicode)]
    public extern static string ToLower(string str);
}

使用后

public static class Native
{
    [LibraryImport(nameof(Native), StringMarshalling = StringMarshalling.Utf16)]
    public static partial string ToLower(string str);
}

有一个分析器和代码修复器可以自动将你的DllImport 属性转换为LibraryImport 。对于Preview 7,它是选择加入的。在你的EditorConfig文件中添加dotnet_diagnostic.SYSLIB1054.severity = suggestion ,以启用转换分析器作为一种诊断。

关于自定义类型的设计文档和细节可以在下面找到 docs/design/libraries/LibraryImportGenerator.

ClientWebSocket升级响应细节

dotnet/runtime#25918

ClientWebSocket 以前没有提供关于升级响应的任何细节。然而,关于响应头和状态代码的信息在失败和成功的情况下都可能是重要的。

在失败的情况下,状态代码可以帮助区分可恢复的和不可恢复的错误(服务器根本不支持web sockets与只是一个微小的瞬时错误)。头信息也可能包含关于如何处理这种情况的额外信息。

即使在网络套接字连接成功的情况下,头信息也是有帮助的,例如,它们可以包含一个与会话相关的标记,一些与子协议版本相关的信息,或者服务器可能很快就关闭了,等等。

使用方法

ClientWebSocket ws = new();
ws.Options.CollectHttpResponseDetails = true;
try
{
    await ws.ConnectAsync(uri, default);
    // success scenario
    ProcessSuccess(ws.HttpResponseHeaders);
    ws.HttpResponseHeaders = null; // clean up (if needed)
}
catch (WebSocketException)
{
    // failure scenario
    if (ws.HttpStatusCode != null)
    {
        ProcessFailure(ws.HttpStatusCode, ws.HttpResponseHeaders);
    }
}

CodeGen中的改进

非常感谢JIT社区贡献者的这些社区PR!

循环优化

在预览版7中,我们对循环优化做了一些改进。

  • PR #71184加强了对循环表的检查,以获得更好的循环完整性检查,如#71084所述。
  • PR #71868不压缩循环周围的块
  • PR#71659调整非模型方法中循环内具有模型的块的权重
  • PR #71504循环提升的改进
  • PR #70271优化了多维数组访问。它将延迟提高到67%(性能链接)。

此外,在PR #71236中为异常处理函数启用了热/冷拆分。

以.NET 7为目标

要以.NET 7为目标,你需要在你的项目文件中使用一个.NET 7目标框架名称(TFM)。比如说:

<TargetFramework>net7.0</TargetFramework>

全套的.NET 7 TFMs,包括具体操作的TFMs如下:

  • net7.0
  • net7.0-android
  • net7.0-ios
  • net7.0-maccatalyst
  • net7.0-macos
  • net7.0-tvos
  • net7.0-windows

我们希望从.NET 6升级到.NET 7应该是很简单的。请报告您在用.NET 7测试现有应用程序过程中发现的任何破坏性变化。

支持

.NET 7是一个**短期支持(STS)**版本,这意味着它将在发布之日起的18个月内获得免费支持和补丁。值得注意的是,所有版本的质量都是一样的。唯一的区别是支持的长度。关于.NET支持政策的更多信息,请参阅.NET和.NET Core官方支持政策

我们最近将 "当前 "的名称改为 "短期支持(STS)"。我们正在推出这一变化

突破性变化

修剪和NativeAOT。默认情况下,所有程序集都会被修剪

为了更好地与用户的期望保持一致,并产生更小、更有效的应用程序,修剪现在默认修剪控制台应用程序中的所有组件。这一变化只影响到用PublishTrimmed=true 发布的应用程序,而且只影响到已有修剪警告的应用程序。它也只影响不使用Windows桌面、Android、iOS、WASM或ASP.NET SDK的普通.NET应用程序。

以前的行为

以前,只有在库项目文件中用<IsTrimmable>true</IsTrimmable> 选择的程序集才会被修剪。

新的行为

从.NET 7开始,修剪默认会修剪应用程序中的所有程序集。以前可能使用PublishTrimmed 的应用程序在.NET 7中可能无法使用。然而,只有有修剪警告的应用程序才会受到影响。如果你的应用程序没有修剪警告,行为的改变不应该造成任何不利影响,而且可能会减少应用程序的大小。

例如,一个使用Newtonsoft.JsonSystem.Text.Json ,而不使用源码生成来序列化和反序列化用户项目中的类型的应用程序,在变化之前可能是正常的,因为用户项目中的类型被完全保留了。然而,一个或多个修剪警告(警告代码ILxxxx )会出现。现在,用户项目中的类型被修剪了,序列化可能会失败或产生意外的结果。

如果你的应用程序确实有修剪警告,你可能会看到行为或异常的变化。例如,一个使用Newtonsoft.JsonSystem.Text.Json ,不使用源码生成来序列化和反序列化用户项目中的类型的应用程序,在变化之前可能是正常的,因为用户项目中的类型是完全保留的。然而,一个或多个修剪警告(警告代码ILxxxx )会出现。现在,用户项目中的类型被修剪了,序列化可能会失败或产生意外的结果。

建议的行动

最好的解决办法是解决你的应用程序中的所有修剪警告。要恢复到以前的行为,将TrimMode 属性设置为partial ,这是.NET 7之前的行为。

<TrimMode>partial</TrimMode>

默认的.NET 7+值是full

<TrimMode>full</TrimMode>

其他突破性变化

你可以通过阅读《.NET 7中的突破性变化》文件,找到最新的.NET 7中的突破性变化列表。它按领域和版本列出了突破性变化,并附有详细解释的链接。

要想知道哪些破坏性变化是被提议的,但仍在审查中,请关注提议的.NET破坏性变化GitHub问题

路线图

.NET的发布包括产品、库、运行时间和工具,并代表了微软内部和外部多个团队的合作。你可以通过阅读产品路线图了解这些领域的更多信息:

结束语

我们感谢您对.NET的支持和贡献。请试一试.NET 7预览版,并告诉我们你的想法!