Null checking with primary constructor in C# 12

Null checking with primary constructor in C# 12


7

I using C# 12.
In C# 12 I can use primary constructor:

public class UserService(IUnitOfWork uow) : IUserService
{

}

Before C# 12 I used null checking for items that I inject in constructor:

public class UserService : IUserService
{
    private readonly IUnitOfWork _uow;

    public UserService(IUnitOfWork uow)
    {
        ArgumentNullException.ThrowIfNull(uow);
        _uow = uow;
    }
}

Now how can I do null checking in C# 12 ?
Is it need to use fail fast with primary constructor ?

4

  • That's null checking, not fail fast. The primary constructor doesn't define a field, it defines a parameter that's in scope for the entire class. You can still use null checking in the field assignment.

    – Panagiotis Kanavos

    7 hours ago


  • 2

    @PanagiotisKanavos: In this case, it's both: OP wants the code to crash early, when UserService is initialized, rather than late, when uow is accessed.

    – Heinzi

    7 hours ago


  • 5

    Be aware that if you use a primary constructor, the field that it introduces is NOT READONLY. Which is quite annoying. See Nick Chapsas's video about it

    – Matthew Watson

    7 hours ago


  • 3

    @MatthewWatson: Indeed. Fortunately, the C# team thinks the same and has announced that they want to fix this in the next version (probably with an optional readonly modifier for PC parameters).

    – Heinzi

    7 hours ago


1 Answer
1


8

As far as I know if you want to switch to primary constructors one of the easiest options would be to introduce field/property:

public class UserService(IUnitOfWork uow) : IUserService
{
    private readonly IUnitOfWork _uow = uow 
         ?? throw new ArgumentNullException(nameof(uow));
}

Note that you can also name the field the same as your constructor parameter (_uow -> uow), if you don’t want to clutter your class with an additional name (as suggested by Heinzi) which has additional benefit of shadowing the mutable primary ctor parameter by an immutable field.

You can also encapsulate the logic into helper method. Something along these lines:

public class UserService(IUnitOfWork uow) : IUserService
{
    private readonly IUnitOfWork uow = uow.IsNotNull();
}

public static class Check
{
    [return:NotNull]
    public static T IsNotNull<T>(this T t,
         [CallerArgumentExpression("t")] string? paramName = null) where T : class
    {
        ArgumentNullException.ThrowIfNull(t, paramName);
        return t;
    }
}

3

  • 3

    If you don't use the helper method, private readonly IUnitOfWork _uow = uow ?? throw new ArgumentNullException(nameof(uow)); is a bit shorter. You can also name the field the same as your constructor parameter (_uow -> uow), if you don't want to clutter your class with an additional name: Yes, private ... uow = uow.IsNotNull(); looks strange, but it works.

    – Heinzi

    7 hours ago


  • 5

    Naming the field and the PC parameter the same has the additional advantage that your mutable PC parameter is now shadowed by an immutable field.

    – Heinzi

    7 hours ago


  • 1

    Thank you @Heinzi , updated! As for the field name – followed the convention from OP. Added as a remark to the answer.

    – Guru Stron

    7 hours ago



Leave a Reply

Your email address will not be published. Required fields are marked *