Five cool C# features: Before and After
Tags: beginners, csharp, tutorial
Published: 2021-10-11 14:16:07

_I originally posted an extended version of this post [on my blog](https://canro91.github.io/2021/09/13/TopNewCSharpFeatures/) 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](https://canro91.github.io/2021/01/18/LinqGuide/).

## 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()`,

```csharp
string.Format("Hello, {0} {1}", title, name);
```

But, if we forgot to add one parameter,

```csharp
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.
```

After with string interpolation,

```csharp
$"Hello, {title} {name}";
```

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,

```csharp
string name = ReadNameFromSomewhere();
if (name == null)
{
    name = "none";
}
else
{
    name.Trim();
}
```

After,

```csharp
string name = ReadNameFromSomewhere();
name?.Trim() ?? "none";
```

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

<figure>
<img src="https://images.unsplash.com/photo-1569783899817-a49d2d25287c?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=400&ixid=MnwxfDB8MXxhbGx8fHx8fHx8fHwxNjIwNjc4MTQx&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=600" alt="Tools on a workbench" />

<figcaption>Photo by <a href="https://unsplash.com/@oxaroxa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Oxa Roxa</a> on <a href="https://unsplash.com/s/photos/tools?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption>
</figure>

## 3. out variables

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

Before,

```csharp
int count = 0;
int.TryParse(readFromKey, out count);
```

After,

```csharp
int.TryParse(readFromKey, out var count);
```

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,

```csharp
int.TryParse(readFromKey, out _);
```

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,

```csharp
Tuple<string, string> Greet() { }

var greeting = Greet();
var name = greeting.Item1;
```

After,

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

var greeting = Greet();
var name = greeting.Name;
```

Even better,

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

var (Salutation, Name) = Greet();
```

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

```csharp
(_, string name) = Greet();
```

## 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,

```csharp
var employee = CreateEmployee();
if (employee is SalaryEmployee)
{
    var salaryEmployee = (SalaryEmployee)employee;
    DoSomething(salaryEmployee);
}
```

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

```csharp
if (employee is SalaryEmployee salaryEmployee)
{
    DoSomething(salaryEmployee);
}
```

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

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

    // other cases...        
}
```

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

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

    case SalaryEmployee salaryEmployee:
        DoSomethingElse(salaryEmployee);
        break;

    // other cases...
}
```

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](https://imcsarag.gumroad.com) to download my ebooks and check my courses._

_Happy coding!_