Cleaner constructors with throw expressions in C# 7

When creating classes it’s important to create constructors that don’t allow creating objects in an invalid state. I blogged about this in the past (in polish – Czy programiści .NET zapomnieli o konstruktorach?). To prevent this we add validations in constructors. One of the most common is validating if object passed to constructor isn’t null. This is boooring code that you just have to type in (Resharper helps here) and before C# 7 and throw expressions it introduces it was taking a lot of space in constructor.

Typical validation in constructor

public ClientService(
     IClientsRepository clientsRepository,
     IClientsNotifications clientsNotifications)
{
    if (clientsRepository == null)
    {
        throw new ArgumentNullException(nameof(clientsRepository));
    }
    if (clientsNotifications == null)
    {
        throw new ArgumentNullException(nameof(clientsNotifications));
    }

    this.clientsRepository = clientsRepository;
    this.clientsNotificator = clientsNotifications;
}

Every time I have to write this code I regret I’m in „always wrap blocks of code in curly braces” and „curly braces always on new line” camps ;). So many lines for such a  small value.

A lot of typing, not a lot of programming

is what I say about this kind of code.

After some time you are so tired of this that you extract those validations to a class.

public ClientService(
    IClientsRepository clientsRepository,
    IClientsNotifications clientsNotifications)
{
    Ensure.NotNull(clientsRepository, nameof(clientsRepository));
    Ensure.NotNull(clientsNotifications, nameof(clientsNotifications));

    this.clientsRepository = clientsRepository;
    this.clientsNotifications = clientsNotifications;
}

Cleaner constructors with less typing

If you are using C# 7 you can use one of it’s new features – throw expressions. It let’s you rewrite the code like this.

public ClientService(
    IClientsRepository clientsRepository,
    IClientsNotifications clientsNotifications)
{
    this.clientsRepository = clientsRepository ?? throw new ArgumentNullException(nameof(clientsRepository));
    this.clientsNotifications = clientsNotifications ?? throw new ArgumentNullException(nameof(clientsNotifications));
}

I think it’s a lot better now (ignore poor code formatting on this blog, it’s two lines in VS). And in fact VS2017 suggests this refactoring (IDE0016 C# Null check can be simplified).

visual-studio-2017-suggests-to-use-throw-expression

Usefull in property setters too

Throw expressions can also make your property setters a lot terser.

public string Property
{
    set
    {
        if (value == null)
        {
            throw new ArgumentNullException();
        }

        backingField = value;
    }
}

can become

public string Property
{
    set
    {
        backingField = value ?? throw new ArgumentNullException();
    }
}

or even (together with expression body – IDE0027 C# Use expression body for accessors)

public string Property
{
    set => backingField = value ?? throw new ArgumentNullException();
}

Use with caution

Remember that suggestion to use throw expression is only a suggestion. If you apply this change mindlessly you can introduce some bugs or side effects. Imagine this method:

public void NotifyClients(string message)
{
    if (message == null)
    {
        throw new ArgumentNullException(nameof(message));
    }
    var clients = clientsRepository.GetClientsToNotify(...);
    // some other long running operation, possibly with side effects

    var n = new Notification();
    n.Clients = clients;
    n.Message = message;

    // more code
}

After applying this suggestion you will end up with

public void NotifyClients(string message)
{
    var clients = clientsRepository.GetClientsToNotify(...);
    // some long running operation, possibly with side effects
    var n = new Notification();
    n.Clients = clients;
    n.Message = message ?? throw new ArgumentNullException(nameof(message));

   // more code
}

which is probably not what you would write yourself.

Throw expressions, used with caution, can make your constructors and property setters  a lot terser yet still expressive.

Reklamy

2 uwagi do wpisu “Cleaner constructors with throw expressions in C# 7

  1. I think, that in these days this isn’t a big issue. In ninety percent of apps we use IOC containers, to construct the logical (those doing stuff 😉 ) part of objects. So instead of nullcheck i would expect rather an exception after resolve fail. Also, in predictet failure points, i much prefer an Integration checks on stratup. This give me confidence that, if there are failures(and null pointer is a failure), then even my app won’t start in incorrect state, and this approach can save a lot of deffensive code in rest of app. A Second case is invalid data provided, in POCOs, Models etc. This stuff belongs to validation which is diffrent responsibility in my opinion.

    Regards!

    Polubienie

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

w

Connecting to %s