Five cool C# features: Before and After

Cesar Aguirre - Oct 11 '21 - - Dev Community

I originally posted an extended version of this post on my blog a couple of weeks ago.

C# is a language in constant evolution. It has changed a lot since its initial versions in the early 2000's. Every version brings new features to write more concise and readable code. These are my 5 favorite C# features and how it was working before them. Well, I'm not including LINQ in this top, I have a whole guide about LINQ with examples.

1. String interpolation: $"Hello, {name}"

Before with string.Format(), we could miss a parameter or add them in the wrong order. If we forgot a parameter, we will get a FormatException.

With string interpolation, we can inline variables directly in the string we want to build. To use string interpolation, before the opening quote of your string, let's add $ and wrap our variables around {}.

Before with string.Format(),

string.Format("Hello, {0} {1}", title, name);
Enter fullscreen mode Exit fullscreen mode

But, if we forgot to add one parameter,

string.Format("Hello, {0} {1}", title/*, I forgot to add the name parameter*/);
// ^^^
// System.FormatException:
//    Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
Enter fullscreen mode Exit fullscreen mode

After with string interpolation,

$"Hello, {title} {name}";
Enter fullscreen mode Exit fullscreen mode

Now, it's clearer if we're missing a parameter or if we have them in the wrong order.

2. Null-conditional (?.) and null-coalescing operators (??)

Starting from C# 6.0, we have two new operators: null-conditional ?. and null-coalescing ?? operators. These two new operators helps us to get rid of null values and the evil NullReferenceException.

With the null-conditional ?. operator, we access a member's object if the object isn't null. Otherwise, it returns null.

The null-coalescing ?? operator evaluates an alternative expression if the first one is null.

Before,

string name = ReadNameFromSomewhere();
if (name == null)
{
    name = "none";
}
else
{
    name.Trim();
}
Enter fullscreen mode Exit fullscreen mode

After,

string name = ReadNameFromSomewhere();
name?.Trim() ?? "none";
Enter fullscreen mode Exit fullscreen mode

It executes Trim() only if name isn't null. Otherwise, name?.Trim() returns null. But, with the ?? operator, the whole expression returns "none".

Tools on a workbench

Photo by Oxa Roxa on Unsplash

3. out variables

We can inline the variable declaration next to the out keyword using the var keyword.

Before,

int count = 0;
int.TryParse(readFromKey, out count);
Enter fullscreen mode Exit fullscreen mode

After,

int.TryParse(readFromKey, out var count);
Enter fullscreen mode Exit fullscreen mode

Instead of declaring a variable, we can use discards _ to ignore the output value. Do you know discards from other languages? Now, C# have them too. For example,

int.TryParse(readFromKey, out _);
Enter fullscreen mode Exit fullscreen mode

I'm not a bit fan of methods with out references. But, with this feature I like them a bit more. I prefer tuples.

4. Tuples

Speaking of tuples...Now we can access tuple members by name. We don't need to use Item1 or Item2 anymore.

We can declare tuples wrapping its members inside parenthesis. For example, to declare a pair of coordinates, it would be (int X, int Y) origin = (0, 0).

We can use named members when declaring methods and deconstructing returned values.

Before,

Tuple<string, string> Greet() { }

var greeting = Greet();
var name = greeting.Item1;
Enter fullscreen mode Exit fullscreen mode

After,

(string Salutation, string Name) Greet() { }

var greeting = Greet();
var name = greeting.Name;
Enter fullscreen mode Exit fullscreen mode

Even better,

(string Salutation, string Name) Greet() { }

var (Salutation, Name) = Greet();
Enter fullscreen mode Exit fullscreen mode

Again, we can use discards when deconstructing tuples. Like this,

(_, string name) = Greet();
Enter fullscreen mode Exit fullscreen mode

5. Pattern matching

With pattern matching, we have more flexibility in control flow structures like switch and if. Let's see a couple of examples.

On one hand, we can avoid casting types inside if statements.

Before without pattern matching, we needed to cast types,

var employee = CreateEmployee();
if (employee is SalaryEmployee)
{
    var salaryEmployee = (SalaryEmployee)employee;
    DoSomething(salaryEmployee);
}
Enter fullscreen mode Exit fullscreen mode

After, with pattern matching, we can declare a variable in the condition,

if (employee is SalaryEmployee salaryEmployee)
{
    DoSomething(salaryEmployee);
}
Enter fullscreen mode Exit fullscreen mode

On another hand, we can use a when clause inside switch.

Before, we had to rely on if statements inside the same case, like this

var employee = CreateEmployee();
switch (employee)
{
    case SalaryEmployee salaryEmployee:
        if (salaryEmployee.Salary > 1000)
        {
            DoSomething(salaryEmployee);
        }
        else
        {
            DoSomethingElse(salaryEmployee);
        }
        break;

    // other cases...        
}
Enter fullscreen mode Exit fullscreen mode

Now, with pattern matching, we can have separate cases,

var employee = CreateEmployee();
switch (employee)
{
    case SalaryEmployee salaryEmployee when salaryEmployee.Salary > 1000:
        DoSomething(salaryEmployee);
        break;

    case SalaryEmployee salaryEmployee:
        DoSomethingElse(salaryEmployee);
        break;

    // other cases...
}
Enter fullscreen mode Exit fullscreen mode

I found it more readable this way. Let's keep the conditional case before the one without conditions.

Voilà! These are only five of my favorites C# features. It was kind of hard to choose only 5 of them. There've been a lot of changes in the latest versions of the C# language.

Which ones didn't you know about? Which ones you use most often? What features would you like to see in future versions? I would like to see discriminated unions in C#.


Hey, there! I'm Cesar, a software engineer and lifelong learner. Visit my Gumroad page to download my ebooks and check my courses.

Happy coding!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .