这是重复的代码,但它几乎不会成为问题,因为这会导致彻底改变您的代码库吗?您是否需要更改其中许多支票?几乎不。看一眼这篇博文 https://blog.ploeh.dk/2014/08/07/why-dry/这有更多细节。
说实话,当谈到我的注入构造函数 https://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/,我几乎不再添加这些 null 检查,因为我知道我的 DI 容器在自动装配这些类型时不会将 null 引用注入到我的构造函数中。这使我根本不用编写所有这些空检查。
有些人可能会说我现在在编写代码时考虑了 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 {
// Use ReferenceEquals in case T overrides equals.
if (object.ReferenceEquals(null, instance)) {
// Call a method that throws instead of throwing directly. This allows
// this IsNotNull method to be inlined.
ThrowArgumentNullException(paramName);
}
return instance;
}
private static void ThrowArgumentNullException(paramName) {
throw new ArgumentNullException(paramName);
}
}
使用 C# 8不可为 null 的引用类型 https://github.com/dotnet/roslyn/issues/227,默认情况下可以将引用类型设置为不可空:
public UserManager(User user, IStateManager stateManager)
{
_user = user;
_stateManager = statemanager;
}
请注意,这只会导致编译时强制,而不是运行时强制。所以不会抛出异常。
这可能会随着 C# 9 的改变而改变。有人建议使用!
symbol:
public UserManager(User user!, IStateManager stateManager!)
{
_user = user;
_stateManager = statemanager;
}