generic types for ML, mandatory members, and more

The final version will be released in November, but for now we invite you under the cut, where to start our C# development course we talk about the new preview and remind you that you have the opportunity to influence the development of the language.


C# 11 already nearing completion. This post is about features in Visual Studio 17.3 or features not covered in April and February editions of Visual Studio.

What’s new in preview boils down to three main areas that we’re focusing on as we develop C# 11:

  • Improved object initialization: support for object constructors and initializers is now easier with any rules for modifiable and non-modifiable members. Here are the elements of the new language functionality:
  • Required members (keyword required).
  • fields ref.
  • Generic math support: You can use one algorithm you write with many numeric types. This simplifies statistics collection, machine learning, and other computationally intensive C# and .NET applications. This includes:
  • Static interface members: abstract and virtual.
  • Relaxing right shift requirements.
  • Unsigned right shift operator.
  • Numeric operator IntPtr.
  • Developer Productivity: New language features will make your work more productive. First of all, the scope of application has been expanded nameof.

All of these functions are described below with links to sections. documentationwhere you can learn more about them. To test these features, turn on the preview feature in your project. Explanations are given in the article. “What’s New in C# 11”.

Improved object initialization

Mandatory Members allow you to write the types of classes and structures with required call operators. For example, here is the type Person:

public class Person
{
    public string FirstName { get; init; }
    public string LastName {get; init; }
}

Call statements must have object initializers that set properties FirstName and LastName. Prior to version 17.3, the compiler could not force callers to set these properties, while a constructor with required parameters is the only way to ensure that the user has set properties. FirstName and LastName. Keyword required tells the compiler and callers that the properties should be set:

public class Person
{
    public required string FirstName { get; init; }
    public required string LastName {get; init; }
}

All call statements must include property object initializers FirstName and LastName, otherwise the compiler reports that the required members are not set and throws an error. Thus, the developer will solve this problem immediately, and will not return to it at the stage of project delivery.

If type Person was used with a legacy compiler and includes a constructor to set properties, this does not prevent you from using required members. To apply them, existing constructors must use the attribute SetsRequiredMembers:

public class Person
{
    public required string FirstName { get; init; }
    public required string LastName {get; init; }

    [SetsRequiredMembers]
    public Person(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }

    public Person() {}
}

Attribute SetsRequiredMembers requires the constructor to set all required parameters. The compiler knows that Person(string firstName, string lastName) are the parameters that need to be set. A parameterless constructor does not include this attribute either, so call statements that use this constructor must have all required members initialized.

In the examples above, the changes concerned properties. But required members apply to field declarations as well.

In the preliminary version, in the initial form, also implemented значения полей ref and scoped. Now the fields ref can be used in types ref struct. Keyword scoped allows you to limit the lifetime of parameters ref. At the moment, descriptions of functions and changes in the new version is the best available documentation on this topic. We found several situations where language updates were required to safely apply the new feature. These updates will appear in a later preview version, and the documentation for it will reflect the functionality of the final version.

Support for math with generics

Added a number of functions to support math with generics. The new functionality will probably come in handy only in difficult situations with writing algorithms that must work with different types of numbers. But, even if you do not write such algorithms, you can benefit indirectly, because the runtime uses the functionality from the list below:

Appearance in the interface static abstract and virtual members will affect most of the calculations with generic types. They allow you to declare operators and other static methods directly from the interface. Classes that implement an interface must support static abstract and other methods declared in interfaces.

Compiler allows method calls static, including statements, at compile time. At the same time, there is no dynamic dispatch mechanism, as for instance methods, in this case. AT docks the specific rules for writing this function are explained in more detail.

Other features of the language smooth out some differences in numeric types and make it easier to write generalized mathematical algorithms. The right shift operator no longer requires the second operand to be of type int. Any integer data type will do! Types nint and nuint are synonyms System.IntPtr and System.UIntPtr respectively. You can use these keywords instead of the corresponding types, and the new parsers allow and even encourage you to do so. Finally, the unsigned right shift operator (>>>) avoids type casting when performing an unsigned shift.

These and other changes have affected the work of mathematics with generic types at runtime. Other changes include, for example, custom statements with overflow checking. Language enhancements allow the runtime command to make better use of all .NET numeric types. These features also come in handy when implementing contracts using operators or other static methods.

Developer Productivity

Now operator nameof can be used together with method parameters. That is, you can use the operator nameof when declaring method attributes:

[return: NotNullIfNotNull(nameof(url))]
string? GetTopLevelDomainFromFullUrl(string? url)

Try it yourself

We invite you to download pre-release versions Visual Studio 2022. You can also download the latest preview .NET 7. Once installed, you will be able to evaluate the new features yourself. To do this, create or open a project in C# and set the tag LangVersion meaning Preview.

The Visual Studio preview brings us closer to the full feature set of C# 11. As we develop the new version of the language, we continue to invest in the development of various aspects. Based on your feedback, we have made adjustments, and now it’s time to download preview version of Visual Studio, test new features and tell us what you think of it. We’re listening intently as we work on the final releases of the C# 11 and .NET 7 updates.

Our courses will help you become a sought-after IT professional from the very beginning or level up. 45% discount with promo code HABR:

45% discount with promo code HABR

Similar Posts

Leave a Reply