As one of my languages du jour, I've always had a fondness for C#. It was one of the first high-level languages that I learned in college and it's been part of my daily professional life for the better part of ten years. One of the things that's always been enjoyable about the language is the concept of constant innovation.
Features are constantly being adapted from other languages (looking at you F#, Kotlin, Typescript, and more) to help add features that would be greatly desired, extend existing functionality, or just apply an ample sprinkling of syntax sugar. I thought with the new year just beginning, let's take a look at some of the proposed features that are slated to find their way into the flagship Microsoft language in the near future!
It's worth noting that this is by no means a complete list and everything in this list, as with all things in active development, is subject to change / never happen.
So, let's get into it!
Using All the Things
One of the proposals that has been championed in the next release of C# has been the concept of extending using
statements to improve resource management. At present, a using statement can require a bit of ceremony, however this proposal would add support for using statements to be used in a declarative fashion:
if (condition)
{
using var file1 = new FileStream("...");
using var file2 = new FileStream("...");
}
This approach would handle freeing up the resources for any variables decorated with the using
statement when the scope was closed. Another facet of the proposal is the concept of using pattern matching to identify the existence of a Dispose() method on a given class, which will be called similar to the example above when the scope has ended:
switch(...)
case someCase:
using var connection = new SqlConnection();
break;
Support for this feature does not require the targeted class to implement the IDisposible
interface, but instead just contain a Dispose() method.
Check Yourself Before You Wreck Assign
A common pattern that you'll commonly see within applications is the use of a simple "is null
" check prior to some assignment statement like the following:
if (something == null)
{
something = someValue;
}
This proposal recommends introducing a new binary operator that aims to simplify this syntax similar to the improvements made with the null
-coalescing operator:
something ??= someValue;
It's fairly low hanging fruit, but it provides some syntactic sugar for a common pattern that you're sure to see in many, many applications.
Null Checks Kotlinified No More
No one really likes writing countless null
checks. Lines upon lines of if
statements with nested exceptions being thrown, it's gross. In a vein similar to the previous feature, this proposal aims to eliminate the need for explicit null checking by allowing an operator !
to be added to a parameter to indicate to the compiler that a given value will not be null.
It would transform a snippet like the following:
int CountWords(string sentence)
{
if (sentence is null)
{
throw new ArgumentNullException(nameof(sentence));
}
}
Into a much terser, uncluttered form:
int CountWords(string sentence!)
{
}
Let the Constructor Do the Work
Another proposal that has been or in some phase of discussion since C# 6 has been the idea of primary constructors, a feature that's been found in languages like Typescript, Kotlin, and other languages. The basic idea behind primary constructors is that they would simplify writing class constructors and boilerplate code in general by implicitly creating private fields from the arguments passed in by the constructor itself.
Let's look at an example of a class with a few private
, readonly
properties:
public class Widget
{
private readonly int _foo;
private readonly WidgetConfiguration _config;
public Widget(int foo, WidgetConfiguration config)
{
_foo = foo;
_config = config;
}
}
The proposal would remove the need for the boilerplate field declarations as the constructor itself would handle creating the arguments passed in:
public class Widget
{
public Widget(int _foo, WidgetConfiguration _config)
{
}
}
If That Wasn't Simple Enough... How About Records?
If you enjoyed the last proposed feature, then you may find yourself doing a double-take with this one. Another proposal that has been toyed with for a while is the concept of records. Records are a simplified form for declaring classes and structs that supports some new features to simplify working with them (such as caller-receiver parameters and with expressions).
public class Widget
{
public readonly string Foo;
public readonly string Bar;
public Widget With(string foo = this.Foo, string bar = this.Bar) => new Widget(foo, bar);
}
We can see this demonstrated below:
var existingWidget = new Widget("foo", "bar");
var clonedWidget = existingWidget.With(bar: "buzz");
Records will also support the use of positional pattern matching along with the use of destruction in tandem to do some things like this:
var widget = new Widget("foo", "bar");
if (widget is Widget("foo", var bar)) {
Console.WriteLine(bar);
}
Records are one of the more involved features being proposed in C# 9, so if you are curious or want to learn more about them, I'd highly recommend checking out the full proposal on them here, which contains a wide range of examples, use cases, and more.
But Wait - There's More!
The features that were covered in this post are some of the more practical ones that might see everyday use, but these were by no means all of the current proposals. I'd encourage you, if you are interested in learning more about what else might be on the menu at the related milestone for C# 9 on GitHub.
There you'll find tons of additional features that weren't mentioned here such as:
Finally - the C# language is open-source and is always looking for contributors, opinions, and any folks that love the language to share their thoughts on what could make it better.
CodeProject