Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Throw Expressions in C# 7

Learn how to use C# 7's new feature to throw exceptions from expression-bodied members, null-coalescing expressions, and conditional expressions.

Nov 28, 2018 • 5 Minute Read

Introduction

An exception is a runtime error in a program that violates a system or application constraint, or a condition that is not expected to occur during normal execution of the program. Possible causes of exceptions include attempting to connect to a database that no longer exists, when a program tries to divide a number by zero, or opening a corrupted XML file. When these occur, the system catches the error and raises an exception. Catching exceptions is a way of handling these unexpected errors by defining a block of code that will be run when an exception is thrown.

C# 7 came with a feature that allows us to throw exceptions from expression-bodied members, null-coalescing expressions, and conditional expressions. In this guide, I'll show you how to use throw expressions.

Throwing Exceptions from Exceptions

Let's look at an example of a class and how it validates the business rule before throwing exceptions.

      using System;

namespace MyApp
{
    class Account
    {
        public Account(string name, int balance)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }
            Name = name;
            Balance = balance;
        }
        public string Name { get; private set; }
        public int Balance { get; private set; }
        public bool IsBlocked { get; set; }

        public string GetLastName()
        {
            var parts = Name.Split(' ');
            if (parts.Length < 2)
            {
                throw new InvalidOperationException("Invalid name!");
            }
            return parts[1];
        }

        public void Credit(int amount)
        {
            if (IsBlocked)
            {
                throw new InvalidOperationException("The transaction cannot be performed on a blocked account");
            }
            Balance = amount + Balance;
        }

        public void Debit(int amount)
        {
            if (IsBlocked)
            {
                throw new InvalidOperationException("The transaction cannot be performed on a blocked account");
            }
            Balance = Balance - amount;
        }
    }
}
    

The class above has properties Name, Balance, and IsBlocked. There are some places in the code we've used the throw statement to raise an exception. In the constructor, it checks if the Name property is null. If it is null, it throws an exception. The GetLastName method raises an InvalidOperationException exception if the value in Name property does not contain two names separated by whitespace. Likewise, both Credit and Debit methods throw an exception if the account is marked as blocked. We can shorten the length of the code by throwing those exceptions from expressions.

To refactor the constructor, we will remove the if statement and replace it with a null coalescing operator then apply the throw statement from the expression as follows:

      public Account(string name, int balance)
{
    Name = name ?? throw new ArgumentNullException(nameof(name));
    Balance = balance;
}
    

Likewise, we can also throw exceptions from the ternary operator. We can apply it to GetLastName, Debit, and Credit methods as follows:

      public string GetLastName()
{
    var parts = Name.Split(' ');
    return parts.Length > 1 ? parts[1] : throw new InvalidOperationException("Invalid name!");
}

public void Debit(int amount)
{
    Balance = IsBlocked ? throw new InvalidOperationException("The transaction cannot be performed on a blocked account") : (Balance - amount);
}

public void Credit(int amount) => Balance = IsBlocked ? throw new InvalidOperationException("The transaction cannot be performed on a blocked account") : (amount + Balance);
    

The methods Debit and Credit perform a similar operation, except that one removes from the Balance while the other adds. We changed Credit to be an expression-bodied method and left Debit with the standard method declaration. This shows that we can apply it to any expression-bodied member of a class. For example, if we were to define a non-functioning method so we can implement it later. We can define that expression-bodied method as public string GetFirstName() => throw new NotImplementedException();.

Wrapping Up

C# 7 introduced throw expressions, which allows us to throw exceptions from expressions. This applies to expressions in expression-bodied members, null coalescing operator, and conditional expressions like the ternary operator. In many places where an expression might be valid, a throw expression can be used to directly throw an Exception. It’s a nice addition to the language and in the example shown in this post, you should notice that it can help write less code. At compile time, they’re re-written and expressed with similar code to how we would have declared them without the throw expression.