Today we released .NET 7 Preview 7. This is the last preview for .NET 7 and the next version will be our first release candidate (RC). The dates for .NET Conf 2022 have been announced! Join us November 8-10, 2022 to celebrate the .NET 7 release!
Visual Studio 2022 17.3 also released today with GA support for .NET Multi-platform App UI (MAUI). Read the .NET MAUI announcement and tune into .NET Conf: Focus on MAUI that is live streaming now!
This preview of .NET 7 includes improvements to System.LINQ, Unix file permissions, low-level structs, p/Invoke source generation, code generation, and websockets.
You can download .NET 7 Preview 7, for Windows, macOS, and Linux.
- Installers and binaries
- Container images
- Linux packages
- Release notes
- Known issues
- GitHub issue tracker
.NET 7 Preview 7 has been tested with Visual Studio 17.4 Preview 1. We recommend you use the preview channel builds if you want to try .NET 7 with Visual Studio family products. If you’re on macOS, we recommend using the latest Visual Studio 2022 for Mac preview. Now, let’s get into some of the latest updates in this release.
Simplified ordering with System.LINQ
System.Linq now has the methods Order and OrderDescending, which are there to order an IEnumerable according to T.
IQueryable also supports this now.
Note: This change does not introduce a new language feature to
System.Linq.Expressions.
Usage
Previously, you had to call OrderBy/OrderByDescending by referencing the own value.
var data = new[] { 2, 1, 3 };
var sorted = data.OrderBy(static e => e);
var sortedDesc = data.OrderByDescending(static e => e);
Now, you can write:
var data = new[] { 2, 1, 3 };
var sorted = data.Order();
var sortedDesc = data.OrderByDescending();
Support for Unix file modes
Previously, .NET had no built-in support for getting and setting Unix file permissions, which control which users can read, write, and execute files and directories. P/Invoking manually to syscalls isn’t always easy because some are exposed differently on different distros. For example, on Ubuntu you may have to pinvoke to __xstat, on RedHat to stat, and so on. This makes a first-class .NET API important.
In Preview 7, we introduced a new enum:
public enum UnixFileMode
{
None,
OtherExecute, OtherWrite, OtherRead,
GroupExecute, GroupWrite, GroupRead,
UserExecute, UserWrite, UserRead,
...
}
and APIs File.GetUnixFileMode and File.SetUnixFileMode that get and set the file mode on either a path or a handle (file descriptors). As well as a new property on FileInfo and DirectoryInfo named UnixFileMode.
There is also a new overload of Directory.CreateDirectory and a new property on FileStreamOptions to allow you to create a directory or file with a particular mode in one shot. Note that when you use these, umask is still applied, as it would if you created the directory or file in your shell.
Usage
// 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);
See all new Unix File Mode APIs.
A big thank you goes out to @tmds, a long-term contributor from Red Hat, who proposed, designed, and implemented this feature.
Low-level struct improvements: ref field support
The .NET 7 runtimes now have full support for ref fields within ByRefLike types (that is, ref struct). There was extensive language design behind this much requested feature that users can read about: low-level struct improvements. With this feature, types previously requiring specialized handling in the runtimes (for example, Span<T> and ReadOnlySpan<T>), can now be fully implemented in C#.
LibraryImport P/Invoke source generator
The LibraryImport source generator is now available in a supported manner to all users. The culmination of more than 18 months this source generator is designed to be a drop-in replacement for the majority of DllImport uses, both in the runtime product and in user code. The .NET libraries have all adopted LibraryImport and have been shipping with source generated marshalling code since .NET 7 Preview 1.
The source generator ships with the .NET 7 TFM and is readily available for consumption. In order to get the benefit of the source generated marshalling, replace usages of DllImport with LibraryImport. There are Analyzers and Fixers that can assist with this process.
Usage
Before
public static class Native
{
[DllImport(nameof(Native), CharSet = CharSet.Unicode)]
public extern static string ToLower(string str);
}
After
public static class Native
{
[LibraryImport(nameof(Native), StringMarshalling = StringMarshalling.Utf16)]
public static partial string ToLower(string str);
}
There is an analyzer and code-fix to automatically convert your DllImport attributes to LibraryImport. For Preview 7, it is opt-in. Add dotnet_diagnostic.SYSLIB1054.severity = suggestion to your EditorConfig file to enable the conversion analyzer as a diagnostic.
Design documentation and details on marshalling custom types can be found under docs/design/libraries/LibraryImportGenerator.
ClientWebSocket upgrade response details
ClientWebSocket previously did not provide any details about upgrade response. However, the information about response headers and status code might be important in both failure and success scenarios.
In case of failure, the status code can help to distinguish between retriable and non-retriable errors (server doesn’t support web sockets at all vs. just a tiny transient error). Headers might also contain additional information on how to handle the situation.
The headers are also helpful even in case of a successful web socket connect, e.g., they can contain a token tied to a session, some info related to the subprotocol version, or the server can go down soon, etc.
Usage
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);
}
}
Improvements in CodeGen
Many thanks to JIT community contributors for these community PRs!
- @MichalPetryka fixed the issue #71632 in PR #71633 Make getTypeForPrimitiveValueClass treat different signs as different types.
- @shushanhf made 2 fixes in LoongArch64.
- @singleaccretion made 20 PR contributions during Preview 7.
- @SkiFoD optimized to use Min/Max intrinsics if one of arguments is constant (PR #69434).
- For Arm664, @a74nh implemented the first part of #67894 in PR #71616 that generates csel and ccmp for conditional comparison and selection instructions (issue #55364).
Loop Optimizations
In preview 7, we made several improvements on Loop Optimizations.
- PR #71184 strengthens checking of the loop table for better loop integrity checks as described in #71084.
- PR #71868 Do not compact blocks around loops
- PR #71659 Adjust weights of blocks with profile inside loops in non-profiled methods
- PR #71504 Improvements to loop hoisting
- PR #70271 optimized multi-dimensional array access. It improved the latency by up to 67% (Performance Link).
In addition, Hot/Cold splitting is enabled for Exception Handling funclets in PR #71236.
Contributor spotlight: Hugh Bellamy
A huge “Thank you” goes out to all our community members. We deeply appreciate your thoughtful contributions. We asked contributor @hughbe to share his thoughts.