Guanxuan.NET 6 RC (Release Candidate) 2

Keywords: .NET

We are pleased to release. NET 6 RC(Release Candidate) 2. It is the second of the two "go live" candidate versions supported in the production environment. Over the past few months, the team has focused on quality improvement. There are many new features in this release, but we will fully integrate them when we are close to the end. The team is currently validating the end-to-end workflow to find areas where the design intent and technical reality have not yet fully matched. This causes the maintainers in the team to modify the bug to achieve this goal.

We have heard from users that upgrading production sites to. NET 6 is both "boring" (non event) and "exciting" (significant performance improvement). Not surprisingly, we believe RC2 will continue this trend.

You can download for Linux, macOS, and Windows  .NET 6 Release Candidate 2.

see also  .NET MAUI  and ASP.NET Core   Post to learn more about what's new in client and Web application scenarios.

The. NET conference is a free, three-day virtual developer event to celebrate the major version of. NET. This year,. NET 6 will be released at the. NET conference from November 9 to 11. We hope you can Write down the date and listen on time . Visual Studio 2022 preview 5 is also released today. They also announced that a release event will be held on November 8. You can   Visual Studio blog Read all relevant content on.

We are in this interesting part of the cycle to support the production of new versions. We sincerely encourage it. If you need guidance on how to deal with it, you can contact us. Many enterprises have begun to contact, and some have begun production. We also helped the Microsoft team run on the RC version. Some Microsoft teams are already in production on RC1, and we look forward to more help on RC2. This includes   . NET web site.

. NET 6 RC2 has been tested and approved Visual Studio 2022 Preview 5 Support is also released today. Visual Studio 2022 will support. NET 6, which Visual Studio 2019 does not. Similarly, MSBuild 17.x will support it, while 16.x does not. If you want to use. NET 6, you need to upgrade to Visual Studio 2022.

Visual Studio 2022, which supports the Mac version, is currently incompatible with. NET 6 RC2. We are solving this problem.

View new Dialogue post , conduct an engineer to engineer in-depth discussion on the latest. NET functions.

. NET 6 RC1 post Focus on basic functions, many of which can not be fully realized until. NET 7. This paper focuses on the improvement of C# 10 and template. It also includes updates (including major changes) for macOS and Windows Arm64. Let's have a look.


C# 10 Is an important part of the. NET 6 version. To a large extent, C# 10 is a further evolution of existing concepts and functions, such as records and patterns. It also includes features -- global usage and file scoped namespaces -- that can help you simplify your code and write fewer boilerplate files. These specific improvements are the basis for the template changes discussed later in this article. You can .NET 6 See the examples used in this section. I'll add more examples in the last post of. NET 6.

Record structs

C# 10 adds support for Record structures. This new feature is similar to c# 9 (class based) records, but there are some major differences. In most cases, Record structures are added for integrity, so that structures can enjoy the same recording advantages as classes. However, the team did not simply structure records, but decided to keep the structure records consistent with ValueTuple, just as the class records match. Due to this design method, the properties of Record structures are variable by default, while the properties of Record class are immutable. However, you can declare a read-only Record structures, which is immutable and matches the Record class semantics.

At a higher level, Record structures will not replace Record classes, and we do not encourage the migration of Record classes to Record structures. The same guidelines for using class vs structures apply to Record classes and Record structures. In other words, before choosing to use Record, you should choose between classes and structures.

Let's look at record structures and Record class What is the difference:

Battery battery = new("CR2032", 0.235, 100);WriteLine(battery);while (battery.RemainingCapacityPercentage > 0){    battery.RemainingCapacityPercentage--;}WriteLine(battery);public record struct Battery(string Model, double TotalCapacityAmpHours, int RemainingCapacityPercentage);

This example of record structures produces the following results.

Battery { Model = CR2032, TotalCapacityAmpHours = 0.235, RemainingCapacityPercentage = 100 }
Battery { Model = CR2032, TotalCapacityAmpHours = 0.235, RemainingCapacityPercentage = 0 }

As mentioned earlier, the most obvious difference is that the record structure attribute is variable by default. This is the main difference between structure and record structure syntax. I also rewritten this example with a read-only record structure, as shown below.

Battery battery = new("CR2032", 0.235, 100);
while (battery.RemainingCapacityPercentage > 0)
    Battery updatedBattery = battery with {RemainingCapacityPercentage = battery.RemainingCapacityPercentage - 1};
    battery = updatedBattery;
public readonly record struct Battery(string Model, double TotalCapacityAmpHours, int RemainingCapacityPercentage);

You will see it almost with Example of (class) Record I published for C# 9 Same.

Let's review the records of C# 9. They provide a The concise syntax is to define data oriented classes with similar structures . They favor invariance and provide concise syntax - with expressions - for immutable and friendly replication. People may be surprised that we began to use classes to implement functions similar to structures. Most of the time, developers use classes rather than structures because of reference passing rather than value semantics. In most cases, classes are the best choice and easy to use.

Structure records are very similar to class records:

  • They use the same syntax (except struct or class in the definition).

  • They allow custom member definitions (new in C#10) to use fields on (by default) attribute members.

  • They allow you to customize member behavior using init or variable attributes.

  • They support expressions. In fact, beginning with C# 10, all structure types support expressions.

Structural records are different from class records:

  • Record structures can be defined with record structures or read-only record structures.

  • Record classes are defined with records or record classes.

  • By default, the record structures property is mutable (get/set).

  • By default, the record class attribute is immutable (get/init).

The asymmetric (non) variability between Record structures and Record classes may surprise or even disgust some readers. I'll try to explain Ideas behind design . Because semantics are passed through values, structures gain almost no benefit from immutability as classes. For example, if a structure is a key in a dictionary, the (copy of the structure) key is immutable and the lookup can only be performed by equality. At the same time, the design team believes that ValueTuple can be regarded as an anonymous record structure, and record structures can be regarded as a derivative of ValueTuple. This works only if the record structure contains variability and support fields, which is what the team decides to do. In addition, inclusion variability reflects differences in structure and classes.

If you prefer the immutable behavior of the record structure, you can get it by adding the readonly keyword.

Looking at structs generally, key functionality is common:

  • The equivalence check provided by the runtime is the same for all structures.

  • All structures can be used with expressions to create non mutated copies, which is a new feature in C# 10.

Global usings

global using allows you to specify a namespace that you want to be available in all source files, just as it is declared in each source file. It can also be used with static and aliases. This feature allows a common set of using declarations to be used and extended to more using lines that are no longer needed. This is most relevant to named namespaces, but can be used for any namespace.

The following syntax can be used in various forms:

  • global using System;

  • global using static System.Console;

  • global using E = System.Environment;

These declarations only need to be declared once in compilation. There are four modes to declare global using.

  • In Program.cs, the root using statements are upgraded to global using to make them global to the whole program.

  • In the globaluses. CS file (or similar name), all global using statements are managed centrally.

  • In the project file, use the following syntax.

  • In your project file, use the statement (for the msbuild SDK that your application depends on) to enable the default platform. The syntax is as follows.

The following MSBuild syntax can replace the. cs file in (using a method similar to the previous example).

  •  <Using Include="System"/>

  •  <Using Include="System.Console" Static="True"/>

  •  <Using Include="System.Environment" Alias="E"/>

You can enable platform defined implicit using statements in < propertygroup >.

  • <ImplicitUsings>enable</ImplicitUsings>

Implicit use of different msbuild SDKs . Microsoft.NET.Sdk defines a basic set, and other SDKs define additional sets.

If you use the MSBuild function, you can see valid results in the files generated in the obj directory, as shown below.

PS C:\Users\rich\app> type .\app.csproj | findstr Using    <ImplicitUsings>enable</ImplicitUsings>    <Using Include="System.Console" Static="True"/>    <Using Include="System.Environment" Alias="E"/>PS C:\Users\rich\app> type .\obj\Debug\net6.0\app.GlobalUsings.g.cs// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.NET.Http;global using global::System.Threading;global using global::System.Threading.Tasks;global using E = global::System.Environment;global using static global::System.Console;

You can see that Microsoft.NET.Sdk has added several global using statements to the. Globaluses. G.cs file. Note that the global:: operator is not required and can be safely ignored in order to understand the generated syntax.

File and namespace declarations

The declaration of file scope namespace is another feature of C# 10, which aims to reduce indentation and the number of lines.

The syntax of this function is as follows:

namespace Foo;

It is an alternative to the traditional three line syntax:

namespace Foo{}

Three line syntax can be nested. Single line syntax does not support nesting. Each file can have only one file scope declaration. It must precede all types defined in the file, much like a three line syntax.

Namespace is incompatible with top-level statements. The top-level statement exists in the top-level namespace. This also means that if you add additional methods to the Program class and use the partial class syntax, the partial Program class also needs to be in the top-level namespace.

This feature is very similar to Single line using declaration added to C# 8.

Const and interpolated string

You can now assign the interpolated string to the const variable. The use and reading of interpolation strings are intuitive and can be used anywhere. They can now be used with const, provided that the placeholder value is also a constant.

The following example illustrates a possible example:

const string Bar = "Bar";const string DoubleBar = $"{Bar}_{Bar}";WriteLine(DoubleBar);

Many other improvements to string interpolation are described in string interpolation in C# 10 and. NET 6.

Extended attribute mode

You can now reference nested properties or fields in the property schema. For example, the following pattern is now legal:

{ Prop1.Prop2: pattern }

Previously, you needed to use a more detailed form:

{ Prop1: { Prop2: pattern } }

You can see the use of this more compact form in the following example, such as Reading.PM25.

List<Status> statuses = new()
    new(Category.Normal, new(20, false, 20)),
    new(Category.Warning, new(20, false, 60)),
    new(Category.Danger, new(20, true, 60)),
    new(Category.Danger, new(100, false, 20))
foreach (Status status in statuses)
    string message = status switch
        {Category: Category.Normal} => "Let the good times roll",
        {Category: Category.Warning, Reading.PM25: >50 and <100} => "Check the air filters",
        {Reading.PM25: >200 } => "There must be a fire somewhere. Don't go outside.",
        {Reading.SmokeDetected: true } => "We have a fire!",
        {Category: Category.Danger} => "Something is badly wrong",
        _ => "Unknown status"
record struct Reading(int Temperature, bool SmokeDetected, int PM25);
record struct Status(Category Category, Reading Reading);
enum Category

. NET SDK: Modern C# project template

We updated it in Preview 7 . NET SDK template , using the latest C# features and patterns. There was important feedback on these changes, in part because the build started to fail. As part of the initial template update, we have enabled it by default for. NET6(NET 6.0) projects, including applications updated from. NET 5 to. NET 6 Implicit use (also known as opt out). That has changed . We have updated the SDK, so all new features are optional. The response to this change (made in RC1) was positive.

There is also feedback that some people don't like the new simplified Program.cs file, including Top level statement . We have modified the top-level statement improvement , and continue to use it for the template. We hope that most developers who like traditional methods can directly add additional methods themselves.

The following language features are used in the new template:

  • Asynchronous Main

  • Top level statement

  • New target typed expression

  • global using directive

  • File scope namespace

  • Nullable reference type

We built all these features because we thought they were better than the previous alternatives. Templates are the easiest and best way to guide new developers and new applications to the best mode. The C# design team firmly believes in using fewer lines and fewer characters to specify a given concept or operation and reduce unnecessary repetition. This is what most of these new features support. Nullable differs in that it produces more reliable code. Every application or library that uses nullable is unlikely to crash in production. Software is too complex for humans to see errors like compilers.

A common theme of these features is that they reduce interference and increase prompts when you view code in the code editor. Now, more important aspects pop up. For example, if you see a using statement in a given file, it is a special statement required outside the implicit set. You should be able to copy / paste code from one file to another without CTRL -. Type to add the required namespace (at least not that much). If you see nullable warnings or errors, you know that your code may be incorrect in some way. Removing indents also has benefits. More code will be visible in the first dozen columns of the editor, rather than just filling them with space characters. People can regard these features as transmitting higher density specificity and significance to the eyes in the process of transmitting information to the brain.

Console template

Let's start with the console template. This is very small.

Program.cs:// see  For more information, Console.WriteLine("Hello, World!");Project files: < project SDK = "Microsoft. Net. SDK" > < propertygroup > < outputtype > exe < / outputtype > < targetFramework > net6.0 < / targetFramework > < implicit uses > enable < / implicit uses > < nullable > enable < / nullable > < / propertygroup > < / Project >

Although the console template is much smaller than its. NET 5 counterpart, there is no reduction in functionality. You can also see that implicit uses is now an optional feature and is enabled in the template.

web template

web templates are also small.

var builder = WebApplication.CreateBuilder(args);var app = builder.Build();app.MapGet("/", () => "Hello World!");app.Run();

The webapi template is closer to a typical ASP.NET Core application. You will soon notice that the separation between Program.cs and startup.cs has been removed. Startup.cs is no longer required.

Program.cs:var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers()// Learn more about configuring Swagger/OpenAPI at;builder.Services.AddSwaggerGen();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){    app.UseSwagger();    app.UseSwaggerUI();}app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();app.Run();
webapi The project file of the template is similar to the console.
<Project Sdk="Microsoft.NET.Sdk.Web">  <PropertyGroup>    <TargetFramework>net6.0</TargetFramework>    <Nullable>enable</Nullable>    <ImplicitUsings>enable</ImplicitUsings>  </PropertyGroup>  <ItemGroup>    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.5" />  </ItemGroup></Project>

You can see in this example that the file scope namespace is used, including in WeatherForecast.cs:

namespace webapi;public class WeatherForecast{    public DateTime Date { get; set; }    public int TemperatureC { get; set; }    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);    public string? Summary { get; set; }}

Target type new is used with WeatherForecastController.cs:

private static readonly string[] Summaries = new[]
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"

In the mvc template, you can see the use of nullable annotations and expression body methods. ​​​​​​​

Windows Forms   Template

The Windows Forms Template has also been updated. It includes most of the other improvements involved in other templates, although not top-level statements. ​​​​​​​

namespace winforms;static class Program{    /// <summary>    ///  The main entry point for the application.    /// </summary>    [STAThread]    static void Main()    {        ApplicationConfiguration.Initialize();        Application.Run(new Form1());    }    }

You can see that single line namespace statements are used, and because implicit use is enabled, there are no platform level using statements.

The WPF template has not been updated as part of the release.

Implicit use

Now I'll show you the practical application of these features. Let's start with implicit usage. When enabled, Each Sdk adds its own set of implicit using statements.

As mentioned earlier, Microsoft.NET.Sdk added several global using statements.

If you disable this feature, you will see that the application is no longer compiled because the System namespace is no longer declared (in this case). ​​​​​​​

PS C:Usersrichapp> type .app.csproj | findstr Implicit
PS C:Usersrichapp> dotnet build
Microsoft (R) Build Engine version 17.0.0-preview-21501-01+bbcce1dff for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
  Determining projects to restore...
  All projects are up-to-date for restore.
  You are using a preview version of .NET. See:
C:UsersrichappProgram.cs(2,1): error CS0103: The name 'Console' does not exist in the current context [C:Usersrichappapp.csproj]

Another option is to use the global using feature, which allows you to use only the namespace you want, as shown in the following example. ​​​​​​​

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <OutputType>Exe</OutputType>    <TargetFramework>net6.0</TargetFramework>    <ImplicitUsings>disable</ImplicitUsings>    <Nullable>enable</Nullable>  </PropertyGroup>  <ItemGroup>    <Using Include="System" />  </ItemGroup></Project>

Now, build the code. ​​​​​​​

PS C:Usersrichapp> type .app.csproj | findstr Using    <ImplicitUsings>disable</ImplicitUsings>  <Using Include="System" />PS C:Usersrichapp> dotnet buildMicrosoft (R) Build Engine version 17.0.0-preview-21501-01+bbcce1dff for .NETCopyright (C) Microsoft Corporation. All rights reserved.  Determining projects to restore...  All projects are up-to-date for restore.  You are using a preview version of .NET. See:  app -> C:UsersrichappbinDebugnet6.0app.dllBuild succeeded.    0 Warning(s)    0 Error(s)Time Elapsed 00:00:00.80

This is not the recommended general model, but it is a good choice for people who want maximum control. In most cases, we expect developers to rely on the implicit use provided by the SDK and take advantage of the explicit global use of namespaces from their own code or the commonly used NuGet package.


I have updated Program.cs to demonstrate nullable reference types. The application calls the list < T > method and returns a t?, In this case, it is an nullable string (string?)

List<string> greetings = new(){    "Nice day, eh?"};string? hello = greetings.Find(x => x.EndsWith("!"));string greeting = hello ?? "Hello world!";Console.WriteLine($"There are {greeting.Length} characters in "{greeting}"");

If the line defining the hello variable is not defined as var, string? perhaps . find returns null "data link title =" list. Find returns null "> List < T >. Find returns null , then it cannot be compiled. If the nullable feature is not enabled, I may miss this problem, which will cause my code to crash due to NullReferenceException exception. That's not good. I use?? and?? in the next line null coalescing operator . in most cases, these two lines of code merge into one line, as shown in the following code. Considering the API that returns nullable reference types, I separate them (in this artificial example) so that you can see the string I use?

string greeting = greetings.Find(x => x.EndsWith("!")) ?? "Hello world!";

In this example, I merge everything into one line. I can now declare the variable as a string because null has adapted to the string following?? string? In this case, only the compiler can see it.

string[] args

Now, I'll quickly solve the problems most people ask about top-level statements, including the args parameter. The args parameter is still available in top-level statements. It's just not so obvious. Here's another program that demonstrates how to use it

string greeting = args.Length > 0 ? string.Join(" ", args) : "Hello World!";WriteLine($"There are {greeting.Length} characters in "{greeting}" in this {nameof(Program)}.");

It produces the following results

PS C:\Users\rich\app> dotnet runThere are 12 characters in "Hello World!" in this Program.PS C:\Users\rich\app> dotnet run Nice day, eh?There are 13 characters in "Nice day, eh?" in this Program.

The application also demonstrates that the Program type is still defined. Program.Main is not By adding a Global static using To my project file, I deleted Console from Console.WriteLine in Program.cs, as shown below.

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <OutputType>Exe</OutputType>    <TargetFramework>net6.0</TargetFramework>    <ImplicitUsings>enable</ImplicitUsings>    <Nullable>enable</Nullable>  </PropertyGroup>  <ItemGroup>    <Using Include="System.Console" Static="True"/>  </ItemGroup></Project>

Define general methods

We've heard feedback from some users who think the real method is better than Local function , especially for Program classes. You can use any model with top-level statements.

I leave the Program unchanged, but switch all functions to the static methods in the Program class and define them in some classes

public partial class Program
    public static string GetTheGreeting(string[] args)
        string greeting = args.Length > 0 ? string.Join(" ", args) : "Hello World!";
        return $"There are {greeting.Length} characters in "{greeting}" in this {nameof(Program)}.";

It produces the same results as the previous example. The Program.Foo.cs file name is arbitrary. In fact, the same is true for Program.cs. You can give these files any name you like. The compiler will find them.

As mentioned earlier, when using top-level statements, the Program type must be in the top-level namespace.

macOS and Windows Arm64 update

In addition to the good news, we also have some breakthrough changes to share. The project supporting macOS and Windows arm64 has been basically completed. With the help of macOS and Windows teams, we have worked on it for more than a year. At first, we thought the project was just to support Arm64 on macOS, and Rosetta 2 will cover x64. It's very simple, just like ISAs, right? No Exactly. With our in-depth study, we found that x64 + Arm64 coexistence is a larger task, mainly focusing on the CLI and installer, including some areas where they need to agree. With RC2, we are delivering a build of. NET to provide the best experience we can imagine.

I'll quickly summarize our progress in Mac OS and Windows Arm64 machines:

  • . NET 6 RC2 realizes the coexistence of Arm64 + x64 by installing Arm64 and x64 versions in different locations. So far, Arm64 and x64 build overlap each other, which led to general safety.

  • You need to uninstall all. NET versions and start from scratch (on macOS and Windows Arm64 machines) to adopt. NET 6 RC2 +. This includes versions before Arm64 and x64,. NET 6 and. NET 6.

  • Versions prior to. NET 6 are not ready for installation.

  • The CLI allows you to use the Arm64 SDK for Arm64 and x64 development (assuming you have installed the required Arm64 and x64 runtime). The reverse is also true.

  • We hope that people will only use the Arm64 SDK because it will have a better experience (native architecture performance; only one SDK needs to be maintained). We will continue the first mock exam to improve the product, making this a simple choice for most developers.

  • For the SDK, we only support. NET 6 + on Arm64. Early SDK builds will be implemented in Blocked on Arm64.

  • For the runtime, we will support all supported versions, Arm64 and x64.

  • . NET 6 RC2 provides a number of. NET 6 end experiences for arm64, including x64 emulation.

  • We want to update the. NET Core 3.1 and. NET 5 runtimes to be consistent with. NET 6 RTM (both temporally and technically). This remains to be determined.

  • The night build of RC2 is currently bad, so you need to wait a few more weeks until we really release RC2 to try all this.

  • The. NET 5 SDK for Windows Arm64 will exit support early with. NET 6 RTM.

We are also considering making some breakthrough changes to dotnet test to unify our views on architectural objectives:

A large part of the project is to enable the x64 runtime through the Arm64 SDK. You can see this in the figure below.

If you want more details, please check dotnet/sdk #21686.


C# 10 provides significant improvements in simplicity and expressibility based on similar features of C# 9. In the past, people could reasonably laugh at C #, because writing just one line of code required so much knowledge of etiquette and object-oriented concepts. Those days have passed, and the template reflects this. Part of the motivation for these changes is to make c# more attractive to new programmers and schools. These simplified changes fundamentally change what you need to start learning and using C # skillfully. In the new default form, it can be directly compared with other languages that similarly start with a single file source file.

We look forward to seeing other projects simplify their new user experience with top-level statements, global usage, logging, and many other modern features. There are many opportunities to create a simpler learning journey for open source projects and commercial products.

We encourage you to use. NET 6RC2. We believe you will find it a reliable version. And the date of the global. NET Conf It will be on November 9 For. NET 6 publishing.

Thank you for being a. NET developer.

Posted by YuriM on Sat, 30 Oct 2021 05:02:58 -0700