C# 12 中主构造函数的 Null 检查

Mil*_*adi 19 c# fail-fast primary-constructor .net-8.0 c#-12.0

我使用 C# 12。在 C# 12 中我可以使用主构造函数:

public class UserService(IUnitOfWork uow) : IUserService
{
}
Run Code Online (Sandbox Code Playgroud)

在 C# 12 之前,我对构造函数中注入的项使用 null 检查:

public class UserService : IUserService
{
    private readonly IUnitOfWork _uow;

    public UserService(IUnitOfWork uow)
    {
        ArgumentNullException.ThrowIfNull(uow);
        _uow = uow;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我如何在 C# 12 中进行 null 检查?
是否需要对主构造函数使用快速失败?

Gur*_*ron 19

据我所知,如果您想切换到主构造函数,最简单的选择之一是引入字段/属性:

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

请注意,如果您不想使用额外的名称(如Heinzi_uow建议)使您的类混乱,您也可以将该字段命名为与构造函数参数相同的名称( -> ) ,这具有隐藏可变主构造函数参数的额外好处通过一个不可变的字段。uow

您还可以将逻辑封装到辅助方法中。沿着这些思路:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 将字段和 PC 参数命名为相同的名称还有一个额外的好处,即您的*可变* PC 参数现在被*不可变*字段遮蔽。 (9认同)
  • 如果不使用辅助方法,`private readonly IUnitOfWork _uow = uow ?? throw new ArgumentNullException(nameof(uow));` 有点短。如果您不想用额外的名称使您的类混乱,您还可以将该字段命名为与构造函数参数相同的名称(`_uow` -&gt; `uow`):是的,`private ... uow = uow.IsNotNull ();` 看起来很奇怪,但它确实有效。 (7认同)