正如所说的那样,你不能使用??运算符来实现这一点(好吧,不使用一些似乎与你使代码更清晰的目标不符的扭曲方法是行不通的)。
当我看到这种模式出现时,我立刻想到了Enforcements。最初来自C++世界,它们在C#中也可以很好地应用,尽管大多数情况下可能不太重要。
这个想法是你采取类似下面这样的东西:
if( condition )
{
throw Exception;
}
并将其转换为:
Enforce<Exception>( condition );
你可以通过默认异常类型来进一步简化。
更进一步地,您可以编写一组Nunit风格的方法来检查不同的条件,例如:
Enforce<Exception>.NotNull( obj );
Enforce<Exception>.Equal( actual, expected );
Enforce<Exception>.NotEqual( actual, expected );
或者,更好的方法是提供一个期望的lambda函数:
Enforce<Exception>( actual, expectation );
非常棒的是,一旦完成了这个步骤,你可以返回实际的参数并强制执行内联。
return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;
... 而这似乎是最接近你需要的。
我之前已经实现过这个功能。有一些小问题,比如如何通用地创建带参数的异常对象 - 选择有些(我当时选择了反射,但通过将工厂作为额外参数传递可能更好)。但总的来说,这非常简单并且可以真正简化很多代码。
我的待办事项清单上有一项是创建一个开源实现。
return this as T ?? that as T ?? other as T ?? throw new NotSupportedException();
来返回结果。但现在我必须使用一个临时变量,检查是否为空,然后返回这个临时变量。这样做有点丑陋。 - Tergiver