这是重复代码,但几乎不会成为问题,因为这可能会在代码库中引起全面更改吗?你是否需要更改许多这些检查?几乎不需要。阅读这篇
博客文章,它详细介绍了这一点。
老实说,当涉及到我的
注入构造函数时,我几乎不再添加这些空值检查,因为我知道我的DI容器不会在自动装配这些类型时将空引用注入到我的构造函数中。这样可以避免我写所有这些空值检查。
有人可能会争论我现在编写代码时考虑了我的DI容器,但我会反驳。我只是编写解决问题所需的最小量代码。在我的情况下,添加这些空值检查对我没有帮助。
但请注意,在我为可重用库编写代码的情况下,我绝对会写这些空值检查,因为我不知道谁在调用该代码。对于不作为注入构造函数(消息、实体、值类型、DTO)使用的构造函数,我确实添加了这些检查。但是,以下是一些如何使此过程更加美好的想法:
您可以添加一个漂亮的帮助程序方法,如下所示:
public UserManager(User user, IStateManager stateManager)
{
Requires.IsNotNull(user, "user");
Requires.IsNotNull(statemanager, "statemanager");
_user = user;
_stateManager = statemanager;
}
然而,这并不能真正帮助减少重复代码,尽管它确实减少了生成的机器代码的实际大小(但这很少是一个问题)。因此,你可以像这样使这个方法返回一个值:
public UserManager(User user, IStateManager stateManager)
{
_user = Requires.IsNotNull(user, "user");
_stateManager = Requires.IsNotNull(statemanager, "statemanager");
}
或者…使用C# 6.0:
public UserManager(User user, IStateManager stateManager)
{
_user = Requires.IsNotNull(user, nameof(user));
_stateManager = Requires.IsNotNull(statemanager, nameof(statemanager));
}
您可以按照以下方式实现此方法:
public static class Requires {
public static T IsNotNull<T>(T instance, string paramName) where T : class {
if (object.ReferenceEquals(null, instance)) {
ThrowArgumentNullException(paramName);
}
return instance;
}
private static void ThrowArgumentNullException(paramName) {
throw new ArgumentNullException(paramName);
}
}
在 C# 8 中,非空引用类型 可以默认为非空:
public UserManager(User user, IStateManager stateManager)
{
_user = user;
_stateManager = statemanager;
}
请注意,这仅仅是在编译时执行的强制措施,而不是运行时执行的强制措施。因此不会抛出任何异常。
C# 9 可能会改变这一点。有一个使用感叹号符号
!
来添加运行时检查的提案:
public UserManager(User user!, IStateManager stateManager!)
{
_user = user;
_stateManager = statemanager;
}