C# was officially released in January 2002, so in a few months’ time we will be able to celebrate the 20th birthday of this programming language. In the meantime, we already know that there will be a new version, namely the tenth. C# 10, together with Visual Studio 2022 and .NET 6, is expected around November 2021. From some official sources and the development team’s blog, it seems that there will be a lot of new features.
This can be a bit traumatising for all that you have to learn, but if you follow the news as it is published, you can find a lot of interesting news. In particular this is a selection of the 5 new features that will be in the new version of C#:
1. Null Parameter Checking
The Null Reference Exception is one of the worst bugs you can have in your code. To protect against this kind of exception, you need a foolproof design of your application and a lot of checks on function parameters. This new feature should help us prevent this problem and make our code more readable and robust.
1.1 Current problem
At the moment, if you want to check that a certain parameter of your function is null, you should do something like this
public SomeFunction(int id, SomeClass newObject) { if (newObject == null) { throw new ArgumentNullException("newObject"); } ... }
In this code we inject newObject of SomeClass into SomeFunction. If the object mentioned is null we should not proceed with the code. Many people will say that with proper application design this problem should not exist, but sometimes it is necessary to do so.
1.2 Characteristic of C# 10
The new version of C# aims to simplify this problem for us with: !!. All you have to do is add two exclamation marks (called “Bang bang”) after the parameter name:
public SomeFunction(int id, SomeClass newObject!!) { ... }
In this example, the code will automatically check if newObject is null. The ArgumentNullException will automatically be thrown if the newObject value is null.
2. Required Properties
Weren’t constructors used more explicitly in the past? Today we don’t write heavy constructors, most of the time we use light constructors, i.e. we define property values directly.
2.1 Current problem
Since a couple of versions of C#, we can create objects using lightweight constructors like this:
var newArticle = new Article { Title = "C# 10 - Top 5 new features", Category = ".NET", ReleaseDate = DateTime.Now() }
The main problem with this approach is that sometimes we need to initialise some property and we don’t do it. For example, we could do something like this, although it doesn’t make sense to create an Article object without a title:
2.2 Characteristic of C# 10
C#10 introduces a new keyword for properties: required. This allows us to make a property mandatory when defining a class. If you try to create an object without the required property you will get an error at compile time.
public class Article { public required string Title { get; init; } public string Category { get; init; } public DateTime ReleaseDate{ get; init; } }
3. Field Keyword
Self-implemented properties are not a new feature; in fact, they first appeared in C# 3. This means that when code is compiled the compiler creates a private, anonymous field that can only be accessed through the get and set accessors of the property.
One of the interesting features that has come with the current version of C# is an init accessor. With this accessor, immutable objects are more flexible and allow the caller to mutate members during the act of construction.
3.1 Current problem
This is all well and good, but when this approach does not suit your problem you are forced to add a field and write the usual property methods. Something like this:
public class Article { private string _title; public string Title { get { return _title; } set { if (value.Trim() == "") throw new ArgumentException("Title can't be empty"); _title = value; } } }
3.2 Characteristic of C# 10
The new version of the C# programming language introduces another new keyword: field. The above code can now be simplified:
public class Article { public string Title { get; set { if (value.Trim() == "") throw new ArgumentException("Title can't be empty"); field = value; } } }
Basically, from C# 10 there will be no need to implement an additional field. This keyword can also be used in the init accessor:
public class Article { public string Title { get; set { if (value.Trim() == "") throw new ArgumentException("Title can't be empty"); field = value; } } public string Category { get; init; } public DateTime ReleaseDate{ get; init => field = value.Date(); } }
4. Global Using
This is a new feature that will greatly simplify your code. As you know, every C# file starts with a list of “using” that are required for the implementation. However, sometimes this is redundant, especially if you are working with ASP.NET a lot of this code is repeated and in general is just “noise” for programmers.
4.1 Current problem
If we take an ASP.NET file as an example, the list of uses is enormous:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.UI; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks;
4.2 Characteristic of C# 10
Another keyword that C# 10 introduces is global. By using global, you will be able to define global usings for the entire project. In general, it is recommended that you create a separate file that will contain these imports, something like usings.cs. This means that the other files in the project can be simplified as they no longer need to add all these using. C# designers refer to this as the elimination of “vertical (space) wastage”.
global using Microsoft.AspNetCore.Builder; global using Microsoft.AspNetCore.Hosting; global using Microsoft.AspNetCore.HttpsPolicy; global using Microsoft.AspNetCore.Identity; global using Microsoft.AspNetCore.Identity.UI; global using Microsoft.EntityFrameworkCore; global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.Hosting; global using System; global using System.Collections.Generic; global using System.Linq; global using System.Threading.Tasks;
5. File Namespaces
By using the global keyword C# eliminates “vertical waste” and with file name spaces it eliminates “horizontal waste”. Basically, this feature aims to solve the indentation problem and is more than a cosmetic change: hopefully it will make the code cleaner.
5.1 Current problem
Nowadays, after the using list, the first thing you see in a C# file is the namespace definition. After that comes the definition of the class. The implementation of the class is already indented at this point. This is what we consider “horizontal waste”.
namespace Blog { public class Article { ... } }
5.2 Characteristic of C# 10
With this feature, you can define the file-level namespace like this:
namespace Blog; public class Article { ... }
Conclusion
In this article, we have had the opportunity to familiarise ourselves with 5 new features that the new version of C# will bring. Some of them seem like a great improvement and it looks like they will affect the way we organise and write C# projects.