DEV Community

Cover image for Leaked C# 11 Features! The best Christmas Gift from Microsoft?
ByteHide
ByteHide

Posted on • Edited on • Originally published at bytehide.com

Leaked C# 11 Features! The best Christmas Gift from Microsoft?

It's already the end of 2021 (I'm still digesting 2019) and I think we would all agree that it has been a very intense and full year, such as the release of C# 10, .NET 6 and many more things. But what's this about C# 11 features coming out already? Wasn't it that Microsoft released C# 10 a month ago?

Is Microsoft really preparing an amazing gift for all C# developers? C# 11 as a gift this Christmas? If this is true, let's see in advance the features that we will find in C# 11.

C# 10 is the latest version of Microsoft's C# programming language. It is designed to be an easy-to-learn programming language for beginners with a focus on simplicity, readability, and productivity.

I already talked about the features of C# 10, but just to refresh your memory, some of the features that are available in C# 10 are:

  • File-scoped namespace declaration
  • Global using directives
  • Loop constructs
  • Record structs
  • handling
  • Improvements on lambda expressions
  • Standardized types and data structures

These features, which were implemented in C# 10, greatly improved the performance of applications, in turn reducing development costs and time.

But let's see what's going on these days with C# 11 and why it's being talked about so much.


What is about C# 11?

As many of us already know, Microsoft released C#10 at the beginning of November, bringing with it many new innovative features making C# a much more versatile language. But since a couple of days ago rumors about C#11 have started to spread in the networks and its possible features have been published in a Reddit thread which makes mention of an changelog in Microsoft's official Github. The features seem very interesting and curious, so let's analyze them:


Generic attributes

This is the first feature talked about in one of the first C# issues on GitHub. Microsoft has had a couple of issues with this promising feature as it encountered some incompatibilities with other tools at the last minute (including crashes and problems compiling). For this reason Microsoft did not officially release this feature in C# 10, but in a preview. Let's see how it works:

As Ashmind has explained with his words in his Proposal:

"For some attributes (e.g. TypeConverterAttribute) that are used to reference types, the current usage looks like this:"

[TypeConverter(typeof(X))]
Enter fullscreen mode Exit fullscreen mode

According to him, this problem has 2 disadvantages:

  • You can't guarantee that the type matches the requirements of the attribute - e.g. has an empty constructor or inherits TypeConverter.

  • The syntax is a bit verbose.

Ashmind suggested that the generic attributes should be supported, including any generic constraints. Followed by an example:

[TypeConverter<X>]
Enter fullscreen mode Exit fullscreen mode

This very good proposal you suggest has a couple of advantages. In his own words:

  • Support for type constraints in type-referencing attributes.

  • Shorter syntax.

  • As far as I know, generic attributes are already supported in IL.


Field Keyword

The favorite feature of many C# developers. We have been analyzing this feature in the previews of C# 10 but it was not officially released (according to Microsoft) due to lack of time, but it seems that they are convinced that in C# 11 it will be released and we will be able to use it with enthusiasm.

To understand the Field Keyword, I will use the explanation of Lachbaer, the creator of this proposal, as it seemed to me to be the best way to understand the Field Keyword:

"Create auto-properties that can also have getters and setters. These can access the automatically created backing field with the field keyword, that acts like a variable, as value does for properties."

Below, Lachbaer explains how this feature works with a very simple example:

A semi-auto-property with an automatic backing-field is created under the follwing cases:

  • there must be either a get; or set; statement,
  • the property has an initializer

Constraint

public string PropertyConstraint {
    get;
    set => field = value ?? throw new ArgumentNullException();
} = "";
Enter fullscreen mode Exit fullscreen mode

The setter defines a constraint. field represents the automatically created backing field. As possible with auto-properties, the backing field is initialized by = "".

Getter logic

public T PropertyAssertedGet {
    int getCounter = 0;   // property scoped field #133
    get 
    {
        getCounter++;
        Debug.Assert (getCounter <= 3,
              "In my code this prop is only called 3 times, somethings terribly wrong.");
        return field;
    }
    set;
}
Enter fullscreen mode Exit fullscreen mode

Event raising

public T PropertyEvent {
    get;
    set
    {
        var oldValue = field;
        OnPropertyChanging(
            new PropertyChangingEventArgs(/* current value */ oldValue, /* new value */ value));
        field = value;
        OnPropertyChanged(
            new PropertyChangedEventArgs(/* current value */ oldValue, /* new value */value));
    }
} = default(T);
Enter fullscreen mode Exit fullscreen mode

In my opinion it is one of the most promising features and the most awaited by all developers in C# 10. It is not known exactly when it will be officially released but we will follow it closely.


List patterns

Let's take a look at Microsoft's textual words on why this feature has not been released in C# 10:

"We have a syntactic design and semantic design for arrays and indexable types, but we will need to some more work for IEnumerable support. We hope to have an initial preview soon into the C# 11 development cycle to help get user feedback on the design choices we've made so far."

¯\( ͡° ͜ʖ ͡°)

List Patterns is a feature suggested by Alrz and is detailed in this way: 

"Lets you to match an array or a list with a sequence of patterns e.g. array is {1, 2, 3} will match an integer array of the length three with 1, 2, 3 as its elements, respectively."

To understand this better, let's look at part of the example he used:

positional_pattern
  : type? positional_pattern_clause length_pattern_clause? property_or_list_pattern_clause? simple_designation?
  ;

property_or_list_pattern_clause
  : list_pattern_clause
  | property_pattern_clause
  ;

property_pattern_clause
  : '{' (subpattern (',' subpattern)* ','?)? '}'
  ;

list_pattern_clause
  : '{' pattern (',' pattern)* ','? '}'
  ;
Enter fullscreen mode Exit fullscreen mode

You can see the complete example and more information in the List Patterns proposal on GitHub.


Static abstracts in interfaces

According to MadsTorgersen (the contributor to this proposal) specifying abstract static members in an interface obligates the classes and structs that implement the interface to include those members, either explicitly or implicitly, in their implementations of the interface in question. It is possible to get access to the members by specifying type parameters that are not prohibited by the interface's restrictions.

The inability to abstract over static members and build generic code that works across types that specify those static members is a major limitation of the present state of the art. This is especially troublesome for member types that only exist in a static form, such as operators, which are particularly difficult to deal with.

Static abstracts in interfaces allows generic algorithms over numeric types to be implemented, which are represented by interface constraints that indicate the existence of certain operators. As a result, the algorithms may be stated in terms of the following operators:

// Interface specifies static properties and operators
interface IAddable<T> where T : IAddable<T>
{
    static abstract T Zero { get; }
    static abstract T operator +(T t1, T t2);
}

// Classes and structs (including built-ins) can implement interface
struct Int32 : , IAddable<Int32>
{
// Explicit
    static Int32 I.operator +(Int32 x, Int32 y) => x + y; 
// Implicit
    public static int Zero => 0;                          
}

// Generic algorithms can use static members on T
public static T AddAll<T>(T[] ts) where T : IAddable<T>
{
// Call static operator    
    T result = T.Zero;
// Use `+`                   
    foreach (T t in ts) { result += t; } 
    return result;
}

// Generic method can be applied to built-in and user-defined types
int sixtyThree = AddAll(new [] { 1, 2, 4, 8, 16, 32 });
Enter fullscreen mode Exit fullscreen mode

You can see the complete example and more information in the Static abstracts in interfaces proposal on GitHub.

MadsTorgesen has also proposed a couple of alternatives, such as Structural constraint:

"An alternative approach would be to have "structural constraints" directly and explicitly requiring the presence of specific operators on a type parameter. The drawbacks of that are:"

  • This would have to be written out every time. Having a named constraint seems better.

  • This is a whole new kind of constraint, whereas the proposed feature utilizes the existing concept of interface constraints.
    It would only work for operators, not (easily) other kinds of static members.


Declarations under or patterns

This is a feature suggested again by Alrz and is detailed in this way:

"Allow pattern variables to be declared in different mutually exclusive patterns. This is the part of pattern-matching proposal that did not make it into C# 9.0."

If each mutually exclusive pattern creates a different set of variables with different types, then the variables will not be firmly assigned in that specific code path, which is what is desired. This contains the or patterns, as well as each occurrence of a switch section, among other things.

A pattern variable may be definitively assigned in a when clause but not in the body of a switch section, for example, as a result of this:

case (int x, 0) a when Use(x, a): // ok
  case (0, int x) b when Use(x, b): // ok
     Use(x); // ok
     Use(a); // error; not definitely assigned
     Use(b); // error; not definitely assigned
     break;
Enter fullscreen mode Exit fullscreen mode

Pattern variables may be defined on both sides of the equation in a recursive way by multiplying them together as follows:

if (e is { A: (int x, 0) or (0, int x) } or
         { B: (int x, 0) or (0, int x) })
{
    Use(x);
}
Enter fullscreen mode Exit fullscreen mode

Again, I recommend reading the Declarations Under or Patterns Proposal in depth on GitHub if you want to know it perfectly.


When will C# 11 be released?

C# 11 at Christmas? I think it will simply be a dream that may come true (it is not the first time that Microsoft works in silence), although seeing all the features that were released in C# 10, it looks unlikely. Anyway, we'll find out in the next few days.

What about you? My dear reader? What do you think will happen with C# 11? Let me know! I would like to know your opinion too :)

If you liked this article, don't forget to FOLLOW US, so that you can be one of the first to read what's new in .NET.

Top comments (6)

Collapse
 
jonasbarka profile image
Jonas Barkå

"It is designed to be an easy-to-learn programming language for beginners"

I've never heard this being one of the main goals of C#.

"In my opinion it is one of the most promising features and the most awaited by all developers in C# 10."

I seriously doubt that field keyword is the most awaited feature. It's nice but still just a bit of syntactic sugar.

From what I know "enum class" (discriminated unions) is the one most devs are waiting for.

"C# 11 at Christmas? I think it will simply be a dream that may come true (it is not the first time that Microsoft works in silence)"

Zero chance. C# 11 will adhere to the now established pattern of the following .NET release cycle. C# 11 with .NET 7 in November 2022.

But as you live one year in the future, you may already have it... 😜

Collapse
 
dcuccia profile image
dcuccia

+1 to discriminated unions. The OneOf Nuget package helps for now, but would be especially great to have completeness checking built into the compiler.

Collapse
 
bausvladimir profile image
Vladimir Baus

"It's already the end of 2022"

Are you sure about that?

Collapse
 
bytehide profile image
ByteHide

For a moment we were in the future🤖

Fixed, thanks for the warning!

Collapse
 
333fred profile image
Fred Silberberg

I know we're all excited about C#. However, this is the disclaimer I put in the first section of the discussion:

Today, we start our initial triaging passes for C# 11. It's important to note that, while we talked about a number of potential features for this cycle, it's extremely unlikely we'll be able to get to all of them. These triage sessions are a good way to see what the LDM is currently thinking about, but please don't try to speculate about what's in or out of C# 11 from them. We don't even know that yet.

The idea that these notes are leaked is wrong. We specifically develop C# out in the open, and I publish the notes from the meeting usually within a few hours of the meeting itself.

You also have some out of date syntax for list patterns, and a few other things that are incorrect. In the future, I'd be happy to review articles before you post them to help avoid the spread of incorrect information. You can email me at frsilb at microsoft, or find me on discord.gg/csharp.

Collapse