dateo. Coding Blog

Coding, Tech and Developers Blog

(Potential) new language features in C# 13

Dennis Frühauff on June 12th, 2024

Every year, Microsoft releases new features for the C# language. For those of you interested in what direction the lead architects are taking us, let's take a look at what has been recently presented on Microsoft Build 2024.


Whether you are new to the .NET ecosystem or among the long-time participants, whether you are stuck on a legacy system using a very old C# language version or always trying out the latest stuff on greenfield projects - whatever your mileage may be, staying up to date is a good idea. Being a self-employed consultant, this is definitely healthy advice for me.


Every year, the C# language's architects Mads Torgersen and Dustin Campbell give us a quick tour of upcoming features for the next version of C#. If you did not find the time to watch that, I'll give you a roundup. And since one of the features sparks a small debate among software enthusiasts, I also want to shed some light on that.


You can find the original talk here on YouTube as well as the latest feature announcements here (which will of course change over the next few months).


Since these features are partly still built from feature branches only, I will not provide a GitHub repo this time to try things out.


params collections

This is a very simple one so we will not spend too much time on it:
We are all very familiar with the params syntax, which lets you pass any number of arguments of a certain type into a method:


public void AddItems(params Item[] items) { ... }

C# 13 will add additional overloads to this signature:


public void AddItems(params IEnumerable<Item> items) {...}
public void AddItems(params IReadOnlySpan<Item> items) {...}

Why is that a good thing? Because it will let you pass collections of arguments into those methods without additional allocation overhead. Any package dependencies that support C# 13 will then automatically benefit from the compiler choosing the most efficient overload in your code on rebuild.


Semi-auto properties

We all know auto-properties which is probably the way we are most often writing our properties these days:


public string Name { get; set; }

This is syntactic sugar for us lazy developers, implicitly instructing the compiler to create backing field and property for us. But what if we ever wanted to just slightly change or validate the value upon setting? Well, we'd write all of that backing field code ourselves again. This can be pretty annoying and repetitive work, so the team did something about it:


public string Name { get; set field => value.ToLower(); }

C# 13 will introduce a new keyword field that represents the backing field that will be generated by the compiler and makes it accessible for us to use in the short-hand notation.


But what if you had an actual field already in your class with this exact same name? Then this will be a breaking change - please be aware of that.


Extensions

Many of us will know classic extensions that let us define additional instance methods to existing types:


public static class StringExtensions
{
  public static class MyExtensions
    {
        public static int WordCount(this string str)
        {
            return str.Split(new char[] { ' ', '.', '?' },
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }
}

And there is already a heated debate around those - people hate or love them for different reasons.
Personally, I am a fan of them whenever they help me wrap convenience code, like parsing, argument conversions, and plain mappings. The only thing I never use extension methods for is business logic.
For example, I would not want to be able to call a business method ToCustomerDiscount() on every string object in my application. That is logic that belongs to a custom class within my code, which is already in my control, so there is no need for an extension method in the first place.


But what if I wanted to add a static method to an existing type? Or properties? This will be made possible (potentially) in the upcoming version of C# and I'll borrow the example from the above-mentioned talk:


implicit extension JsonString for string:
{
  public JsonElement ParseAsJson() => JsonDocument.Parse(s.Trim()).RootElement;

  public static string CreateIndented(JsonElement element) 
    => element.ValueKind != JsonValueKindUndefined 
    ? JsonSerializer.Serialize(element) 
    : Empty;
  
}

explicit extension Customer for JsonElement
{
  public string Name => this.GetProperty("name").GetString()!;
}

What are are seeing are type definitions that let us add functionality to existing type that we do not have access to, like string. Compared to extension methods, we are not limited to instance methods but we can also add properties and static type methods.


The fact that they are implicit indicates that these methods will be present on all string in our code. In the case of the extension for JsonElement the extension is marked as explicit means that it will only be accessible to us once we cast a JsonElement to this type definition:


JsonElement jsonElement = ...;
Customer customer = jsonElement;
var name = customer.Name;

This is essentially a way of looking at an object through a specific set of glasses.
If you are now thinking "Inheritance?", then the answer is not really, because it is a much more efficient, non-allocating, no-overhead way of accessing the underlying object.


One interesting thing happens when we imagine an extension without actual method or property declarations:


public explicit extension DataSet<T> 
  for System.Collections.Generic.Dictionary<string, T> { }

This is now essentially an alias. But since it is actually more of a type definition, it does actually support generics (which alias does not). We can also better control where and how that extension can be used (which alias is permitted through a questionable global keyword).
C# 13 (accidentally, somehow) both improves the way we can use extensions in the future and also gives us a much better alternative to alias which is kind of a dead end anyway to many of us.


As mentioned, there is already an ongoing debate on social media around this feature. People are complaining that C# is being turned into a typescript clone, with extensions watering the purpose of object-oriented programming.


Me, personally, I can definitely see the benefit of extensions and I can only appreciate the work that Mads and his team are putting into the language to make it the best tool for our job.


At the same time, I can also see how misuse of extensions can lead to creating a mess of an application, hiding business decisions in every small pothole of a code base. But obviously, every tool that we are using is usually meant to solve a very specific job, not all of them.
So know your tools, and you'll be alright. Trust me.


Conclusion

This was a short summary of the feature announcement for C# 13 that was given on Microsoft Build 2024. I do hope that there were one or two interesting bits for you to it!



Please share on social media, stay in touch via the contact form, and subscribe to our post newsletter!

Be the first to know when a new post was released

We don’t spam!
Read our Privacy Policy for more info.

We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept All”, you consent to the use of ALL the cookies. However, you may visit "Cookie Settings" to provide a controlled consent.