Early peek at C# 11 features

Kathleen Dollard

Visual Studio 17.1 (Visual Studio 2022 Update 1) and .NET SDK 6.0.200 include preview features for C# 11! You can update Visual Studio or download the latest .NET SDK to get these features.

Check out the post Visual Studio 2022 17.1 is now available! to find out what’s new in Visual Studio and the post Announcing .NET 7 Preview 1 to learn about more .NET 7 preview features.

Designing C# 11

We love designing and developing in the open! You can find proposals for future C# features and notes from language design meetings in the CSharpLang repo. The main page explains our design process and you can listen to Mads Torgersen on the .NET Community Runtime and Languages Standup where he talks about the design process.

Once work for a feature is planned, work and tracking shifts to the Roslyn repo. You can find the status of upcoming features on the Feature Status page. You can see what we are working on and what’s merged into each preview. You can also look back at previous versions to check out features you may have overlooked.

For this post I’ve distilled these sometimes complex and technical discussions to what each feature means in your code.

We hope you will try out these new preview features and let us know what you think. To try out the C# 11 preview features, create a C# project and set the LangVersion to Preview. Your .csproj file might look like:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <LangVersion>preview</LangVersion>
    </PropertyGroup>
</Project>

C# 11 Preview: Allow newlines in the “holes” of interpolated strings

Read more about this change in the proposal Remove restriction that interpolations within a non-verbatim interpolated string cannot contain new-lines. #4935

C# supports two styles of interpolated strings: verbatim and non-verbatim interpolated strings ($@"" and $"" respectively). A key difference between these is that a non-verbatim interpolated strings cannot contain newlines in its text segments, and must instead use escapes (like \r\n). A verbatim interpolated string can contain newlines in its text segments, and doesn’t escape newlines or other character (except for “” to escape a quote itself). All of this behavior remains the same.

Previously, these restrictions extended to the holes of non-verbatim interpolated strings. Holes is a shorthand way of saying interpolation expressions and are the portions inside the curly braces that supply runtime values. The holes themselves are not text, and shouldn’t be held to the escaping/newline rules of the interpolated string text segments.

For example, the following would have resulted in a compiler error in C# 10 and is legal in this C# 11 preview:

var v = $"Count ist: { this.Is.Really.Something()
                            .That.I.Should(
                                be + able)[
                                    to.Wrap()] }.";

C# 11 Preview: List patterns

Read more about this change in the proposal List patterns.

The new list pattern allows you to match against lists and arrays. You can match elements and optionally include a slice pattern that matches zero or more elements. Using slice patterns you can discard or capture zero or more elements.

The syntax for list patterns are values surrounded by square brackets and for the slice pattern it is two dots. The slice pattern can be followed by another list pattern, such as the var pattern to capture the contents of the slice.

The pattern [1, 2, .., 10] matches all of the following:

int[] arr1 = { 1, 2, 10 };
int[] arr1 = { 1, 2, 5, 10 };
int[] arr1 = { 1, 2, 5, 6, 7, 8, 9, 10 };

To explore list patterns consider:

public static int CheckSwitch(int[] values)
    => values switch
    {
        [1, 2, .., 10] => 1,
        [1, 2] => 2,
        [1, _] => 3,
        [1, ..] => 4,
        [..] => 50
    };

When it is passed the following arrays, the results are as indicated:

WriteLine(CheckSwitch(new[] { 1, 2, 10 }));          // prints 1
WriteLine(CheckSwitch(new[] { 1, 2, 7, 3, 3, 10 })); // prints 1
WriteLine(CheckSwitch(new[] { 1, 2 }));              // prints 2
WriteLine(CheckSwitch(new[] { 1, 3 }));              // prints 3
WriteLine(CheckSwitch(new[] { 1, 3, 5 }));           // prints 4
WriteLine(CheckSwitch(new[] { 2, 5, 6, 7 }));        // prints 50

You can also capture the results of a slice pattern:

public static string CaptureSlice(int[] values)
    => values switch
    {
        [1, .. var middle, _] => $"Middle {String.Join(", ", middle)}",
        [.. var all] => $"All {String.Join(", ", all)}"
    };

List patterns work with any type that is countable and indexable — which means it has an accessible Length or Count property and with an indexer an int or System.Index parameter. Slice patterns work with any type that is countable and sliceable — which means it has an accessible indexer that takes a Range as an argument or has an accessible Slice method with two int parameters.

We’re considering adding support for list patterns on IEnumerable types. If you have a chance to play with this feature, let us know your thoughts on it.

C# 11 Preview: Parameter null-checking

Read more about this change in the proposal Parameter null checking.

We are putting this feature into this early preview to ensure we have time to get feedback. There have been discussions on a very succinct syntax vs. a more verbose one. We want to get customer feedback and from users that have had a chance to experiment with this feature.

It is quite common to validate whether method arguments are null with variations of boilerplate code like:

public static void M(string s)
{
    if (s is null)
    {
        throw new ArgumentNullException(nameof(s));
    }
    // Body of the method
}

With Parameter null checking, you can abbreviate your intent by adding !! to the parameter name:

public static void M(string s!!)
{
    // Body of the method
}

Code will be generated to perform the null check. The generated null check will execute before any of the code within the method. For constructors, the null check occurs before field initialization, calls to base constructors, and calls to this constructors.

This features is independent of Nullable Reference Types (NRT), although they work well together. NRT helps you know at design time whether a null is possible. Parameter null-checking makes it easier to check at runtime whether nulls have been passed to your code. This is particularly important when your code is interacting with external code that might not have NRT enabled.

The check is equivalent if (param is null) throw new ArgumentNullException(...). When multiple parameters contain the !! operator then the checks will occur in the same order as the parameters are declared.

There are a few guidelines limiting where !! can be used:

  • Null-checks can only be applied to parameters when there is an implementation. For example, an abstract method parameter cannot use !!. Other cases where it cannot be used include:
    • extern method parameters.
    • Delegate parameters.
    • Interface method parameters when the method is not a Default Interface Method (DIM).
  • Null checking can only be applied to parameters that can be checked.

An example of scenarios that are excluded based on the second rule are discards and out parameters. Null-checking can be done on ref and in parameters.

Null-checking is allowed on indexer parameters, and the check is added to the get and set accessor. For example:

public string this[string key!!] { get { ... } set { ... } }

Null-checks can be used on lambda parameters, whether or not they are surrounded by parentheses:

// An identity lambda which throws on a null input
Func<string, string> s = x!! => x;

async methods can have null-checked parameters. The null check occurs when the method is invoked.

The syntax is also valid on parameters to iterator methods. The null-check will occur when the iterator method is invoked, not when the underlying enumerator is walked. This is true for traditional or async iterators:

class Iterators {
    IEnumerable<char> GetCharacters(string s!!) {
        foreach (var c in s) {
            yield return c;
        }
    }

    void Use() {
        // The invocation of GetCharacters will throw
        IEnumerable<char> e = GetCharacters(null);
    }
}

Interaction with Nullable Reference Types

Any parameter which has a !! operator applied to its name will start with the nullable state being not-null. This is true even if the type of the parameter itself is potentially null. That can occur with an explicitly nullable type, such as say string?, or with an unconstrained type parameter.

When !! syntax on parameters is combined with an explicitly nullable type on the parameter, the compiler will issue a warning:

void WarnCase<T>(
    string? name!!,     // CS8995   Nullable type 'string?' is null-checked and will throw if null. 
    T value1!!        // Okay
)

Constructors

There is a small, but observable change when you change from explicit null-checks in your code to null-checks using the null validation syntax (!!). Your explicit validation occurs after field initializers, base class constructors, and constructors called using this. Null-checks performed with the parameter null-check syntax will occur before any of these execute. Early testers found this order to be helpful and we think it will be very rare that this difference will adversely affect code. But check that it will not impact your program before shifting from explicit null-checks to the new syntax.

Notes on design

You can hear Jared Parsons in the .NET Languages and Runtime Community Standup on Feb. 9th, 2022. This clip starts about 45 minutes into the stream when Jared joins us to talk more about the decisions made to get this feature into preview, and responds to some of the common feedback.

Some folks learned about this feature when they saw PRs using this feature in the .NET Runtime. Other teams at Microsoft provide important dogfooding feedback on C#. It was exciting to learn that the .NET Runtime removed nearly 20,000 lines of code using this new null-check syntax.

The syntax is !! on the parameter name. It is on the name, not the type, because this is a feature of how that specific parameter will be treated in your code. We decided against attributes because of how it would impact code readability and because attributes very rarely impact how your program executes in the way this feature does.

We considered and rejected making a global setting that there would be null-checks on all nullable parameters. Parameter null checking forces a design choice about how null will be handled. There are many methods where a null argument is a valid value. Doing this everywhere a type is not null would be excessive and have a performance impact. It would be extremely difficult to limit only to methods that were vulnerable to nulls (such as public interfaces). We also know from the .NET Runtime work that there are many places the check is not appropriate, so a per parameter opt-out mechanism would be needed. We do not currently think that a global approach to runtime null checks is likely to be appropriate, and if we ever consider a global approach, it would be a different feature.

Summary

Visual Studio 17.1 and .NET SDK 6.0.200 offer an early peek into C# 11. You can play with parameter null-checking, list patterns, and new lines within curly braces (the holes) of interpolated strings.

We hope you’ll check out the C# 11 Preview features by updating Visual Studio or downloading the latest .NET SDK, and then setting the LangVersion to preview.

We look forward to hearing what you think, here or via discussions in the CSharpLang repo on GitHub!

99 comments

Comments are closed. Login to edit/delete your existing comments

  • Денис Оболенский

    I don’t like parameter null checking feature. It doesn’t feels like a nice addition to the language and have already caused a lot of holywars. Why does you introduce a new syntax for this? Why you can’t use existing notnull keyword on the type, not on the parameter name? Why do you use !! on the parameter name? It even contradicts with NRT feature, where strict null’s validation can be added.

    • JesperTreetop

      Putting the !! on the parameter rather than the type is fitting here since it’s the value of the parameter that’s being checked. Things that go with the type should only be there if they describe something about the type. There’s no type anywhere else that can be string!! or string?!!.

      That said, it feels a bit ridiculous and out-of-place that a special two-punctuation-character incantation is introduced just to throw a certain exception.

        • hitesh davey

          notnull keyword on the right is a much better option than !! notation.

          public void DoSomething(string first notnull, string second notnull ) { // code }

          having notnull, on the left, may hinder the practice of writing the code as C# developers are now used to writing and reading the code as “datatype followed by variable name”.

          • Richard Valdivieso

            I think we can try both and using data it is possible to remove the one that is less used?

          • Joey .

            Technically it’d be a modifier for the parameter, like ref or out and thus should come to the left. But agreed, a (contextual) keyword would be more sensible than more sigils.

        • Moreno Gentili

          When nullable reference types are enabled, I should also get the option to – automatically – throw exceptions whenever a null is passed as an argument to a non-nullable parameter.

          Eg. in the .csproj

          <Nullable>enable</Nullable>
          <ArgumentChecking>enable</ArgumentChecking>

          Then I define a method with a non-nullable parameter.

          public void DoSomething(string first) {
            // code
          }

          Finally, when I invoke said method by passing null, an ArgumentNullException is thrown.

          DoSomething(null); // This throws

          PHP is doing it right.
          https://php.watch/versions/8.1/internal-func-non-nullable-null-deprecation

        • Paul Hughes

          There is a lot of double symbols popping up now, ??, !!. If I was a beginner and knew a bit of digital logic i would assume !! was true(which it is, but not understanding it was not null). I prefer when it is written in English what it is I am looking at, I pick up the code faster. I get it though learn new concepts and shorter code. I hope we don’t end up with too many symbols though rather than readable code, one of the reasons I took to C# over languages like Python with no types when going over variables in the code and global and local mess.
          Maybe I’m just getting old.

    • Charles Roddie

      I agree. The NRT project is a success so this feature is not needed. If any consuming project has NRT turned off then that is its problem.

      We considered and rejected making a global setting that there would be null-checks on all nullable parameters.

      Then this code can be generated only in consuming projects with NRTs disabled. This contains the performance impact.

        • Ladislav Burkovsky

          We can have the bang bang implicit in NRT projects and optional outside. Additionally we should have the option to activate/deactivate in code.

        • Dmitrij Lytkin

          Can we start ignoring comments of the people who do not care to understand the feature?
          Now we have a situation where people judge the feature without even trying to understand why it exists and how to use it.
          It’s pity that the bang-bang operator has been removed because of some naive judgments from the community while most of the professionals have shown it a really high appreciation.

    • Jonatas Hudler

      I agree !! syntax is ugly as hell. It adds noise to the code, it is not self explanatory, and makes newcomers overwhelmed (like F#, that contains lots of syntax gotchas and has one of the most ugly syntax ever produced).

    • Kathleen DollardMicrosoft employee

      @Денис Оболенский

      I want to be sure I understand, can you give a code sample of what your notnull suggestion would look like. I want to check that it is one of the alternatives we have.

      We use this on the parameter because it is a feature of that parameter.

      Null Reference Type checking is not strict null validation. It is design time and things can happen at runtime that NRT does not consider.

      • Денис Оболенский

        Sure, I can provide some alternatives:

        1) Using notnull because this keyword is in the language already

        public void DoSomething(notnull string first, notnull string second) { // code }

        2) Using new NRT option here with strict validation (for example, as implemented in typescript, angularc, etc).

         strict 

        3) Using [NotNull] attribute

        public void DoSomething([NotNull] string arg) { //code }

        For me !! seems like an ugly syntax. Yeah, with this feature it’s much easier to write the code, but 80% of the time developers read the code. For me, it’s the same ugly feature, just like

        Type array[]

        declarations in Java.

        Options 1 and 3 will need to write more characters for developers, but they are in billion times easier to understand. And all losses to write more characters could be zeroed by using IDE features for code generation. Option 2 may be less intuitive, but with strict NRT validation it also makes sence.

        • Oscar Järgren

          I approve of this, seems a way better option to handle it.

          Reading code should be easy, not writing it.

          Writing code has never been the hard part, it’s figuring out what you want to do and then understanding it later.

          • hitesh davey

            Well said. You just echoed my views.
            Reading and understanding code is more critical than writing since nowadays we have good AI code completion features.

        • AlseinX

          I am strongly against them.

          1. notnull keyword is a contextual keyword, which means adding extra available context for it is also adding new keyword.

          2. It is a keyword at the beginning of code to opt in or out some language feature that is the really ugly design failure.

          3. An attribute to directly change the logical behavior (at managed level) of a statically compiled code, is not what C# was previously designed to be.

          And, as for that example

          Type array[]

          , I agree with that it is certian to be ugly, but it is because of that modern laguanges turn to use “type expression”, which is a syntax tree to express complexed structural parameterized types, instead of the old C-style (array is not a type but a way of declaring a bunch of variables).

          But parameter null checking is not a type but a sugar that attaches checking behavior to A PARAMETER that is declared as some nullable type, which is not itself a wrapper type. Thus the java array example does not apply.

    • Y Zhang

      I don’t like it either. Besides, it’s also not a good practice if we are talking about “a static method should be thread-safe”

    • Dmitrij Lytkin

      notnull is an expression of 7 symbols, used to define a type constraint. Therefore it is used rarely.
      !! – only 2 symbols of syntax sugar which replaces widely used boilerplate code.
      Having a !! instead of a whole

      if (bla is null) throw new ArgumentNullException(nameof(bla));

      drastically improves readability of function’s logic.

      Can you provide an example on contradiction with NRT?

  • JesperTreetop

    “and must instead use escapes (like rn)”

    I think WordPress is being WordPress and ate the backslashes.

  • Evgeny Muryshkin

    Why !! at all? If parameter is nullable, and there is no explicit check/branch for null in code, exception generation can be implied.

    Advanced mode can check that all calls for this private/internal member already have checked for null and skip it to reduce amount of checks.

    • Michael Taylor

      Auto-generating such code would be a very bad idea. Therefore this really isn’t an option. I can think of several cases where auto-generating such code without prompting from the dev would not work well.

      • Some methods shouldn’t throw an ANE on null but NRE. The use case here is an extension method as they should behave like instance members. Instance members do not throw ANE but NRE. But you should not throw an NRE yourself so the only way to get this to work properly is to reference the instance.
      • In many cases higher level methods already validate arguments and therefore lower level methods should not auto-check as well. This is wasteful and there is no way to know whether such a case exists or not given just a method declaration.
      • Accessibility doesn’t matter in terms of “already checked”. If you could even do such analysis (what if there are cases where the args are checked and others aren’t) it still isn’t reliable. For example a method, irrelevant of accessibility, can be passed as a delegate to other code. There is no way to do code analysis and detect this. Hence you’d have to come up with heuristics to determine when to enable/disable such a feature (e.g. accessibility) and that just makes it a lot harder to understand. It would also then be a breaking change to change the accessibility of a method (currently it generally isn’t if you go from more restrictive to less).
      • Finally, it would be a breaking change to suddenly start throwing ANE in code that didn’t previously. Somebody somewhere could be wrapping that code in typed exception handlers and would suddenly see different behavior.

      Auto-generation of code without a programmer indicating they want it is almost always a bad idea. It must always be opt in.

  • Mark Adamson

    Slice patterns work with any type that is countable and sliceable

    I was surprised to find recently that ImmutableArray doesn’t support Slicing in .net 6. Will that be resolved so that we can use this feature with ImmutableArray and others which I use as standard now?

  • Arturo Torres Sánchez

    After all this I still hate the !! feature, because it essentially means that a plain string input is useless.

    For a method public void Process(string input) now we have three options:

    1. string? input: input can be null. OK.
    2. string input!!: input can never be null. OK.
    3. string input: input shouldn’t be null, but who knows? This last one is essentially deprecated since either 1 or 2 is the one you actually want.

    It’s still vexing to me why this functionality wasn’t included in the existing NRT feature.

    • Kathleen DollardMicrosoft employee

      Your #3 is a good option where NRT is sufficiently protecting your code. This feature is to add a check where you think it is needed in your code.

      There is also a great deal of code that does not yet use NRT. This feature avoids that code being visible and will allow us to do the fastest possible check. However, there is still a performance hit of the null check.

      NRT is strictly design time. Null-checks is the sister runtime feature.

      • Arturo Torres Sánchez

        Your #3 is a good option where NRT is sufficiently protecting your code.

        I mean, if NRT was sufficiently protecting my code, this feature wouldn’t be necessary, would it?

        This feature is to add a check where you think it is needed in your code.

        I think it’s needed in all public methods. Having a plain string input on a public method is now an error. If only there was a way to add the validation without me having to manually add it…

        There is also a great deal of code that does not yet use NRT.

        But code that doesn’t use NRT already is throwing exceptions on nulls everywhere. I don’t see the point of this feature to replace one syntax with another while not solving the underlying issue at all.

        NRT is strictly design time. Null-checks is the sister runtime feature.

        Yes, this is exactly my complaint. NRT being strictly design time is a bad decision in my opinion, and shouldn’t need a “sister” runtime feature.

        • Kathleen DollardMicrosoft employee

          Your #3 is a good option where NRT is sufficiently protecting your code.

          I said that in relation to scenarios where the author of the method understands enough of the context where it is used that they think NRT is sufficient.

  • WDS_ACCOUNT®

    the though is a situation on which the scope retain value of method;

    if( TestMethod(parameters...) ){
     //perform the scope of returning value;
     //value keyword
     x=a+value;
    } else { //[...] }

    is there such a thing? then using the !! null checking (aka: Scope Tuple)…

    if( !!TestMethod(parameters...) ){
     //the !! indicate the feature of null checking; like a tuple
     //scopex keyword
     x=a+scope0;
    
    if( !!TestMethod(parameters...) ){
     //scopex tuple in action;
     x2=a+scope0+scope1;
    } 
    
    } else { //[...] }

    just illustration of idea feature; could avoid boiler plate variables declarations;

    oh and the TestMethod declaration

    dynamic TestMethod(parameters...){}
      • WDS_ACCOUNT®

        C# 11 Preview: Parameter null-checking
        had only followed illustrating the idea with featured sample codes; thanks;

        also the github is too complicated then just commenting it;

    • Oleg Mikhailov

      First, NRT is dead, nobody uses it; second, this feature is for run-time, not for compile-time like NRT.

      • Olivier Spinelli

        Funny. I use it everywhere in my code base. At start I had to use ! at too many places. Nowadays I have nearly none of them.
        I also use them “deeply”, for instance a List<int> will not be serialized like a List<int?> and a List<Person> will not be serialized as a List<Person?> (where Person is a reference type). Really using it’s a real gain.

        Saying “NRT is dead” sounds like saying “You don’t need GC”… LOL.

  • hitesh davey

    Pl, explain why two !! instead of just one ! ?

    Also, I realized that in the last 6yrs or so, too many features are added aggressively to C# lanaguage. Pl control the language release cycle for the major Dotnet release versions only. Give enough time to the developer community around the world to get hold of the new features and take advantage of them. My observation is that by adding too many features it looks like I am writing assembly code, not human-understandable code.

  • Thorsten Sommer

    Thank you Kathleen for this article. Since many other commenters do not like this feature, I would like to speak up for the silent mass of .NET developers. In our enterprise code, parameter null checking will save many thousands of lines of code. This feature complements NRT usefully, in our opinion. We also don’t agree with the opinion that new features have been added too quickly and aggressively in recent years. Each developer can decide for himself how fast or slow to adopt new features in his own code. After all, there are also the long term versions of the SDK (e.g. .NET Core 3.1, .NET 6). In particular, the changes and new language features in recent years have clearly improved C# code for us. Modern C# code is easier to read and understand and is now closer to Python 3 code. We see this as very positive: new employees often have a Python background and thus get into C# code more easily. Over the last 12 months, we have seen an interesting development in our applicants: There are more and more young developers who apply to us explicitly because we write modern C# code. Their motivation? They want to learn modern C# to develop games in Unity or Godot later on. This suits us and we get motivated employees.

    • Gábor Szabó

      I came to second this opinion. The C# language is one of the most rapidly improving languages out there. The only thing that I can argue maybe is there are too many language features which are superseded by vastly superior ones, and they should be deprecated. Most of these have code fixes implemented anyways, so migration shouldn’t be an issue.

      I don’t fully support the idea that we cannot set our null checks to be applied by default. Arturo before said it well, with the nullable ref types feature, the “plain” mode of defining a parameter will be essentially obsolete. I think it should be controlled on a project level, as you shouldn’t have too huge projects anyways, and opt-in/opt-out is always a possible solution. Also, the feature is opinionated enough that it maybe won’t be a good fit for all solutions out of the box, maybe not even new projects. I myself would like it if there was a way to generate opinionated code too for checks. I understand you discarded the idea of using attribute to don’t bloat the code, but maybe you could think about a nice way to bring in something like more typesafe type aliases? Like I could define my own String-like type that is convertible to and from normal strings without issue, but would throw in cases I could explicitly define in code. These should be special “alias” types, that wouldn’t allocate and would behave exactly like the type they alias.

      public alias MyString : string
      {
        public MyString(string!! value) { }
      } 

      I feel a solution like this would benefit the most and would stay closest to what the spirit of C# is and has embraced ever since it was introduced.

    • Олег Нечитайло

      Did you look at something like Fody.NullGuard?

      It solves parameter null checking and integrates seamlessly with NRT.

    • Ian Marteens

      Is “closer to Python 3” a good thing? Python is the worst thing that has happened to IT since the previous century.

    • Cole Brand

      I’m here to third Thorsten’s comment. I get that there are a lot of vocal devs who would love to just remain on C# 1.0, and the truth is, they can. It’s just not a very good experience.

      There was a comment about “how can new developers ever learn all these things” and the answer to that is the same as it has always been: mentorship. If you are complaining about features like these but not helping to mentor new developers, then you are not really creating a very conducive environment for programming, and that is a problem. We should all work together to make development more fun and engaging for everyone.

      As to the comments of “but this feature is garbage, I would never use this” I have only to say to those developers “please don’t use it. You are free to write as many lines of code as you would like. The runtime that you are running on will still use this feature and you will never know that they didn’t write as many lines of code as you did, and that’s ok too.”

      I for one am excited about this feature and looking forward to using it. Saving 20k lines of code is enough of a blessing for me to take it as a good sign.

      I love the new upcoming features. Haters gonna hate. Y’all keep inspiring us! We look forward to it!

    • Brad Bodily

      There are many considerations that go beyond my typical use cases, I’m sure. However, I think of the many, many times I’ve written the same code at the beginning of so many methods, and then I see this statement, “It was exciting to learn that the .NET Runtime removed nearly 20,000 lines of code using this new null-check syntax,” and I picture how many lines of code I could remove, and that makes me look forward to the option of this new syntax.