头图

I am very happy that .NET 6 Preview 5 finally meets you all. We are now in the second half of .NET 6 and are beginning to integrate some important features. .NET SDK workload, which is the basis of our 161080f894c73e .NET unified vision , which can support more types of applications. Like other functions, it is also to better serve the end-to-end user experience.

.NET 6 Preview 5 for Linux, macOS and Windows.

Please refer to ASP.NET Core , EF Core and .NET MAUI for more detailed information about the new features of the web, data access and cross-platform UI solutions.

Visual Studio 2022 Preview 1 is also today .NET 6 Preview 5 included. .NET 6 was also on 161080f894c94c Visual Studio 16.11 and Visual Studio for Mac 8.9 . If you want Visual Studio , we recommend that you use these versions.

You can also check out the new conversation post to learn more about the engineers' ideas on the new features of .NET.

.NET SDK: Optional workload improvements

SDK workload is a new .NET SDK feature that allows us to add support for new application types (such as mobile and WebAssembly ) without increasing the size of the SDK.

Workloads have been added to include list and update instructions. These new features provide a user experience consistent with the final experience we expect. You will be able to quickly build your environment with a few simple instructions and keep it up to date.

  • The dotnet workload list will tell you which workloads are installed.
  • dotnet workload update will update all installed workloads to the latest available version.

The update command queries nuget.org for an updated list of workloads, updates the local list, downloads the new version of the installed workload, and then deletes all old versions of the workload. This is similar to apt update and apt upgrade -y (for Debian-based Linux distributions).

The dotnet workload command set runs in the context of a given SDK. Suppose you have both .NET 6 and .NET 7 installed at the same time. If you use both at the same time, the workload commands will provide different results because the workloads will be different (at least different versions of the same workload).

As you can see, the workload feature is essentially the package manager of the .NET SDK. The workload was originally introduced in .NET 6 Preview 4 .

.NET SDK: NuGet package verification

Package Verification The tool will enable NuGet library developers to verify that their packages are consistent and well-formed.

This includes:

  • Verify that there are no major changes between different versions.
  • The verification package has the same set of public APIs for all specific runtimes.
  • Identify any gaps to the target framework or runtime applicability.

This tool is available through Microsoft.DotNet.PackageValidation .

about this tool will soon be .

.NET SDK: More Roslyn analyzers

In .NET 5, we provide approximately 250 analyzers with the .NET SDK. Many of them already exist, but we will release them separately as NuGet packages. We are to add more analyzer 6 the .NET .

By default, most new analyzers are applied at the Info level. You can configure to enable these analyzers at the Warning level AnalysisMode as follows:

\<AnalysisMode\>AllEnabledByDefault\</AnalysisMode\>

We released the set of .NET 6 analyzers we wanted (plus some extra stuff), and then made most of them public .

Preview 5 includes the following implementations Newell Clark and Meik Tranel Please note that community users contributed other implementations in the previous preview.

ContributorIssueTitle
Newell Clarkdotnet/runtime #33777Use span-based string.Concat
Newell Clarkdotnet/runtime #33784Prefer string.AsSpan() over string.Substring() when parsing
Newell Clarkdotnet/runtime #33789Override Stream.ReadAsync/WriteAsync
Newell Clarkdotnet/runtime #35343Replace Dictionary\<,\>.Keys.Contains with ContainsKey
Newell Clarkdotnet/runtime #45552Use String.Equals instead of String.Compare
Meik Traneldotnet/runtime #47180Use String.Contains(char) instead of String.Contains(String)

.NET SDK: Enable custom protection for the platform compatibility analyzer

CA1416 platform compatibility analyzer identify platform protections, such as OperatingSystem.IsWindows and OperatingSystem.IsWindowsVersionAtLeast. However, the analyzer does not recognize any other protection possibilities , such as platform check results cached in fields or attributes, or complex platform check logic defined in auxiliary methods.

In order to make custom protection possible, we added new attributes SupportedOSPlatformGuard and UnsupportedOSPlatformGuard, you can use the corresponding platform name and/or version annotation to customize the protection object. The flow analysis logic of the platform compatibility analyzer recognizes and respects the content of these annotations.

usage

  [UnsupportedOSPlatformGuard("browser")] // The platform guard attribute
#if TARGET_BROWSER
    internal bool IsSupported => false;
#else
    internal bool IsSupported => true;
#endif

    [UnsupportedOSPlatform("browser")]
    void ApiNotSupportedOnBrowser() { }

    void M1()
    {
        ApiNotSupportedOnBrowser();  // Warns: This call site is reachable on all platforms.'ApiNotSupportedOnBrowser()' is unsupported on: 'browser'

        if (IsSupported)
        {
            ApiNotSupportedOnBrowser();  // Not warn
        }
    }

    [SupportedOSPlatform("Windows")]
    [SupportedOSPlatform("Linux")]
    void ApiOnlyWorkOnWindowsLinux() { }

    [SupportedOSPlatformGuard("Linux")]
    [SupportedOSPlatformGuard("Windows")]
    private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();

    void M2()
    {
        ApiOnlyWorkOnWindowsLinux();  // This call site is reachable on all platforms.'ApiOnlyWorkOnWindowsLinux()' is only supported on: 'Linux', 'Windows'.

        if (_isWindowOrLinux)
        {
            ApiOnlyWorkOnWindowsLinux();  // Not warn
        }
    }
}

Windows Forms: Default font

You can now use Application.SetDefaultFont to set the default font for the application. The mode you use is similar to setting high dpi or visual style.

class Program
{
    [STAThread]
    static void Main()
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

+       Application.SetDefaultFont(new Font(new FontFamily("Microsoft Sans Serif"), 8f));

        Application.Run(new Form1());
    }
}

Below are two examples after setting the default font (using different fonts).

Microsoft Sans Serif, 8pt:

file

Chiller, 12pt:

file

.NET Core 3.0 updated the default font of This change has brought great obstacles to some users from migrating .NET Framework applications to .NET Core. The default font settings make it easy to select the required fonts for the application and remove barriers to migration.

Libraries: Give up support for the old framework

Removing the framework from the package is a change that breaks the source code. However, allowing it to always support all the frameworks we publish also increases the complexity and size of the package. In the past, we used _harvesting_ to solve this problem, that is:

  • We only build for the "current" supported frameworks
  • During the build, we download the early version of the package and cut out the binaries of the earlier framework that we no longer build

Although this means that you can update at any time without worrying that we will delete the framework, it also means that if you use a cut binary file, you will never get any bug fixes or new features. In other words, the assets that have been cut and cannot be serviced are now hidden, because from your point of view, you can continue to update the package to a higher version, even if you are using an old binary file that we no longer update .

Starting from .NET 6 Preview 5, we plan to no longer perform any form of harvesting to ensure that everything we deliver is better served. This means that we will give up support for any version earlier than:

  • .NET Framework 4.6.1
  • .NET Core 3.1
  • .NET Standard 2.0

If you are currently referencing an affected package from an earlier framework, you will no longer be able to update the referenced package to a later version. You can repoint your project to a higher version of the framework or choose not to update the referenced packages (this is usually not a big fallback, because you are already using frozen binaries anyway).

For more detailed information, including a complete list of affected packages, see dotnet/announcement: Remove old framework version .

Library: Microsoft.Extensions

We are always improving this version of the Microsoft.Extensions API. In Preview 5, we focus on hosting and dependency injection. In the preview version 4, we added a source compiler generator for logging when .

Thanks to Martin Björkström] ( https://github.com/bjorkstromm) for dotnet/runtime #51840 (AsyncServiceScope) .

Hosting – ConfigureHostOptions API

We have added a new ConfigureHostOptions API on IHostBuilder to simplify application configuration (such as configuration timeout shutdown):

using HostBuilder host = new()
    .ConfigureHostOptions(o =>
    {
        o.ShutdownTimeout = TimeSpan.FromMinutes(10);
    })
    .Build();

host.Run();

Before Preview 5, the configuration was more complicated:

using HostBuilder host = new()
    .ConfigureServices(services =>
    {
        services.Configure<HostOptions>(o =>
        {
            o.ShutdownTimeout = TimeSpan.FromMinutes(10);
        });
    })
    .Build();

host.Run();

Dependency injection – CreateAsyncScope API

You may have noticed that when the service provider registers the IAsyncDisposable service, its destruction will throw an InvalidOperationException.

The new CreateAsyncScope API provides a very straightforward solution, as shown in the following example:

await using (var scope = provider.CreateAsyncScope())
{
    var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}

The following example demonstrates existing problem cases and demonstrates the previously suggested solutions.

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

await using var provider = new ServiceCollection()
        .AddScoped<Foo>()
        .BuildServiceProvider();

// This using can throw InvalidOperationException
using (var scope = provider.CreateScope())
{
    var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}

class Foo : IAsyncDisposable
{
    public ValueTask DisposeAsync() => default;
}

You can bypass the exception by casting the returned scope to IAsyncDisposable.

var scope = provider.CreateScope();
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
await ((IAsyncDisposable)scope).DisposeAsync();

CreateAsyncScope solves this problem and allows you to use the using statement safely.

Library: JsonSerializer source code generator

The backbone of almost all .NET serialization tools is the reflection mechanism. Reflection is a great feature for some scenarios, but it is not suitable for high-performance cloud-native applications (because it usually needs to deal with a lot of serialization and deserialization and JSON documents). Excessive use of reflection will cause some programs start , memory usage and assembly trimming on 161080f894d0b4.

An alternative to runtime reflection is compile-time source code generation. The source code generator generates C# source files, which can be compiled as part of a library or application build. Generating source code at compile time can provide many benefits for .NET applications, including performance improvements.

In .NET 6, we introduced a new source code generator in System.Text.Json. The JSON source code generator and JsonSerializer work together, and can be configured into a variety of working methods. Whether to use the new source code generator is up to you. It can provide the following benefits:

  • Reduce startup time
  • Improve serialization throughput
  • Reduce private memory usage
  • Remove the use of System.Reflection and System.Reflection.Emit at runtime
  • Allow trim-compatible JSON serialization

For example, the source code generator can generate simpler and more effective assignment/value code for properties, instead of generating get and set methods through Reflection.Emit at runtime (this will use private memory and affect the startup speed), so that performance can be obtained. A greater improvement.

You can use System.Text.Json NuGet package to try out the source code generator. We are proposal including source code generator in the SDK.

Generate optimized serialization logic

By default, the JSON source code generator applies serialization logic for a given serializable type. This provides higher performance than directly using the existing JsonSerializer to generate Utf8JsonWriter In short, the source generator provides a different implementation method that is applied at compile time to optimize the runtime experience of the program.

On a macro level, JsonSerializer is a powerful tool. It has many functions that can improve the serialization and deserialization between .NET types and JSON format (there are even more new features to be implemented!). It is fast, but it also incurs some performance overhead when the serialization routine requires only a subset of functions. Looking ahead, we will update JsonSerializer and the new source code generator at the same time.

Given a simple class:

namespace Test
{
    internal class JsonMessage
    {
        public string Message { get; set; }
    }
}

The source generator can be configured to generate serialization logic for instances of the JsonMessage class. Please note that the class name JsonContext is arbitrary. You can use any class name you want for the generated source code.

using System.Text.Json.Serialization;

namespace Test
{
    [JsonSerializable(typeof(JsonMessage)]
    internal partial class JsonContext : JsonSerializerContext
    {
    }
}

We define a set of JsonSerializer functions through JsonSerializerOptionsAttribute , which are provided by the source code generation mode that provides the best serialization throughput. These functions can be assigned to the source code generator in advance to avoid additional checks at runtime. If this attribute is not declared, the default JsonSerializationOptions will be used at runtime.

As part of the build, the source code generator expands some classes of JsonContext with the following:

internal partial class JsonContext : JsonSerializerContext
{
    public static JsonContext Default { get; }

    public JsonTypeInfo<JsonMessage> JsonMessage { get; }

    public JsonContext(JsonSerializerOptions options) { }

    public override JsonTypeInfo GetTypeInfo(Type type) => ...;
}

A serializer call using this pattern might resemble the following example. This example provides the best performance possible.

using MemoryStream ms = new();
using Utf8JsonWriter writer = new(ms);

JsonContext.Default.JsonMessage.Serialize(writer, new JsonMessage { "Hello, world!" });
writer.Flush();

// Writer contains:
// {"Message":"Hello, world!"}

Or, you can continue to use JsonSerializer, and use JsonContext.Default.JsonMessage to pass an instance of the generated code to it.

JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage);

This is a similar usage, but the overloading method is different.

JsonSerializer.Serialize(jsonMessage, typeof(JsonMessage), JsonContext.Default);

The difference between these two overloads is that the first overload is implemented using typed metadata — JsonTypeInfo\&lt;T\&gt; — the second uses a more general untyped implementation, which performs type testing to Determine whether there is a typed implementation in the context instance. Therefore, it is a bit slow (due to type testing). If there is no source-generated implementation for a given type, the serializer will throw a NotSupportedException. But it will not fall back to a reflection-based implementation (our design makes this clear).

The fastest and most optimized source code generation mode based on Utf8JsonWriter is currently only available for serialization. We will decide whether to provide a deserialization implementation based on Utf8JsonReader in the future based on your feedback.

However, the source code generator also provides type metadata initialization logic, which also facilitates deserialization. To deserialize an instance of JsonMessage using pre-generated type metadata, you can do the following:

JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);

Similar to the serialization above, you can also write:

JsonSerializer.Deserialize(json, typeof(JsonMessage), JsonContext.Default);

Supplementary notes

Library: WebSocket compression

Compression is important for any data transmitted over the network. WebSockets now enable compression . We used the permessage-deflate extension implementation of WebSockets, RFC 7692 . It allows the use of the DEFLATE algorithm to compress the WebSockets message payload.

This feature is one of the highest requirements users have for Networking on GitHub. You can follow our process of providing this API API review 1 and API review 2

to 161080f894d513 Ivan Zlatanov . Thank you Ivan!

We realize that combining compression and encryption may lead to attacks, such as CRIME and BREACH . This means that the secret cannot be sent with user-generated data in a single compression context, otherwise the secret can be extracted. To make users aware of these effects and help them weigh the risks, we renamed the API to DangerousDeflateOptions. We also added the ability to turn off compression for specific messages, so if users want to send a secret, they can send it safely without compression.

Ivan also carried out a follow-up work , when compression is disabled, the memory usage of WebSocket is reduced by about 27%.

Enabling compression from the client is easy, see the example below. However, keep in mind that the server can negotiate settings, such as requesting a smaller window, or rejecting compression altogether.

var cws = new ClientWebSocket();
cws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions()
{
    ClientMaxWindowBits = 10,
    ServerMaxWindowBits = 10
};

Recently, it also added ASP.NET Core's WebSocket compression support . It will be included in the upcoming preview.

Library: Socks proxy support

SOCKS is a proxy server implementation that can handle any TCP or UDP traffic, making it a very versatile system. This is a long-standing community request has been added to NET 6 in .

This change adds support for Socks4, Socks4a, and Socks5. For example, it allows to test external connections via SSH or connect to Tor network .

The WebProxy class now accepts the socks scheme, as shown in the following example.

var handler = new HttpClientHandler
{
    Proxy = new WebProxy("socks5://127.0.0.1", 9050)
};
var httpClient = new HttpClient(handler);

to 161080f894d653 Huo Yaoyuan . Thank you Huo!

Library: Support for OpenTelemetry indicators

As part of our focus on observability part, we have been in for the last few .NET version add support OpenTelemetry of . In .NET 6, we have added to OpenTelemetry Metrics API of support . By adding support for OpenTelemetry , your application can seamlessly interoperate with other OpenTelemetry systems.

System.Diagnostics.Metrics is the .NET implementation OpenTelemetry Metrics API specification The Metrics API is specifically designed for processing raw measurements, and is usually designed to efficiently and simultaneously generate continuous summaries of these measurements.

The API includes the Meter class that can be used to create instrument objects such as counters. The API exposes four instrument classes: Counter, Histogram, ObservableCounter and ObservableGauge to support different indicator scenarios. In addition, the API exposes the MeterListener class to allow listening to the measurements recorded by the instrument for aggregation and grouping.

OpenTelemetry .NET implementation will be extended to use these new APIs, which add support for Metrics observability scenarios.

Sample library measurement record

Meter meter = new Meter("io.opentelemetry.contrib.mongodb", "v1.0");
    Counter<int> counter = meter.CreateCounter<int>("Requests");
    counter.Add(1);
    counter.Add(1, KeyValuePair.Create<string, object>("request", "read"));

Listening example

  MeterListener listener = new MeterListener();
    listener.InstrumentPublished = (instrument, meterListener) =>
    {
        if (instrument.Name == "Requests" && instrument.Meter.Name == "io.opentelemetry.contrib.mongodb")
        {
            meterListener.EnableMeasurementEvents(instrument, null);
        }
    };
    listener.SetMeasurementEventCallback<int>((instrument, measurement, tags, state) =>
    {
        Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
    });
    listener.Start();

Library: BigInteger performance

BigIntegers from decimal and hexadecimal strings has been improved . We have seen up to 89% improvement of , as shown in the figure below.

file

to 161080f894d7dc Joseph Da Silva . Thank you Joseph!

Library: Vector\&lt;T\&gt; now supports nint and nuint

Vector\&lt;T\&gt; now supports the nint and nuint primitive types added For example, this change should make it easier to use SIMD instructions with pointers or platform-dependent lengths.

Library: Support OpenSSL 3

The .NET encryption API supports the use of OpenSSL 3 as the preferred native encryption provider on Linux. If available, .NET 6 will use OpenSSL 3. Otherwise, it will use OpenSSL 1.x.

Library: Add support for ChaCha20/Poly1305 encryption algorithm

The ChaCha20Poly1305 class has been added to System.Security.Cryptography. To use the ChaCha20/Poly1305 algorithm, it must be supported by the underlying operating system. The static IsSupported attribute can be used to determine whether the algorithm is supported in a given context.

  • Linux : OpenSSL 1.1 or higher is required.
  • Windows : Build 20142 or higher (currently need to develop "inside staff" channel)

Thanks to Kevin Jones for supporting Linux. Thank you Kevin!

Interoperability: Objective-C interoperability support

The team has been add in Objective-C support , the goal is to provide a single for the .NET in Objective-C interoperability implementation . So far, the Objective-C interoperating system is built around the Mono embedded API, but we believe that this is not the right way to share across runtimes. Therefore, we created a new .NET API that will support a single Objective-C interoperability experience and will eventually run on two runtimes.

The new Objective-C API for interoperability is NSAutoreleasePool brings two runtime immediate support , to support Cocoa reference counting memory management systems. You can configure 161080f894d971 whether you want each managed thread have an implicit NSAutoreleasePool. This makes it possible to release Cocoa objects on a per-thread basis.

Diagnosis (EventPipe/DiagnosticsServer)-MonoVM

Starting from .NET 6, many diagnostic functions have been added to MonoVM. This enables functions such as managed EventSource/EventListener, EventPipe, and DiagnosticsServer. It supports the use of diagnostic tools, such as dotnet-trace, dotnet-counters, dotnet-stacks, for applications running on mobile devices (iOS/Android) and desktops.

These new features opened in PrefView / SpeedScope / the Chromium, DOTNET-the trace ability to analyze MonoVM generated nettrace files and other tools, or use TraceEvent and other library write custom parsers .

We will continue to include more features, mainly focusing on SDK integration and adapting more local runtime events (Microsoft-Windows-DotNETRuntime) to MonoVM to enable more events in the nettrace file.

Now has the following functions:

  • shared native EventPipe/DiagnosticsServer library between MonoVM and CoreCLR.
  • Add TCP/IP support to DiagnosticsServer and use this configuration to build MonoVM iOS/Android runtime package. Need to support mobile platforms.
  • BCL EventSources runs on MonoVM and sends events to EventPipe.
  • The BCL runtime counters issued by System.Diagnostics.Tracing.RuntimeEventSource are connected to MonoVM and can be consumed from tools such as dotnet-counters.
  • The custom event source runs on MonoVM and sends custom events to EventPipe, which can be used by tools such as dotnet-trace.
  • The custom event counter runs on MonoVM, and the custom counter event is sent to EventPipe, which can be used by tools such as dotnet-counters.
  • The sample analyzer is implemented on MonoVM and sends events to EventPipe. The ability to use dotnet-trace to perform CPU analysis on MonoVM is enabled.
  • The implementation of the dotnet-dsrouter diagnostic tool allows the use of existing diagnostic tools, such as dotnet-trace, dotnet-counters, dotnet-stack, and MonoVM running on mobile targets, without changing the existing tools. dotnet-dsrouter runs a local IPC server, routing all traffic from the diagnostic tool to the DiagnosticsServer running in MonoVM on the emulator/device.
  • Use component-based architecture achieve EventPipe / DiagnosticsServer in MonoVM in.
  • Implementation/expansion of , a diagnostic environment based on file sessions.

iOS CPU sampling (SpeedScope)

The image below demonstrates part of the iOS-initiated CPU sampling session viewed in SpeedScope.

file

Android CPU sampling (PerfView)

The image below demonstrates the Android CPU sampling viewed in PerfView (the main thread in infinite sleep).
file

Runtime: CodeGen

The following changes have been made in RyuJIT.

Community contribution

Thanks to @SingleAccretion for these contributions.

Dynamic PGO

file

JIT loop optimization

LSRA

is included in the "allocated registers" table https://github.com/dotnet/runtime/pull/52513 The differences between the old and new tables:

file

keep the structure registered at

Optimize debugging experience

file

SIMD

Inlining of certain methods involving SIMD or HWIintrinsics should now have improved code generation and performance. We see up to 95% improvement .

file

end

In terms of the breadth and number of features, .NET 6 Preview 5 may be the largest preview to date. You can use source generators and analyzers to see the extent to which Roslyn functions affect low-level library functions. The future has really arrived. We now have a very powerful compiler toolchain that allows us to generate highly optimized and correct code and provide the exact same experience for your own projects.

Now is a good time to start testing .NET 6. It’s too early for us to act on your feedback. Hard to imagine, though we want to 2021 Nian 11 Yue will release , but the feedback window will soon be reduced to only for the high seriousness of the problem. The team conducted a preview for about one and a half years in advance, and will soon turn to focus on quality issues. If you can, try .NET 6.

Thank you for being a .NET developer.

This article is published by the blog one article multi-posting OpenWrite

MicrosoftReactor
109 声望19 粉丝

微软 Reactor 是微软为构建开发者社区而提供的一个社区空间,以“予力多元化社区建设,帮助每一个开发者成就不凡”为使命,旨在通过不定期举办的技术讲座、开发者交流会面及技术沙龙和专题活动,帮助开发者和初创企...