是否可以使用操作员? 并抛出新的exception()?
我接下来有很多方法:
var result = command.ExecuteScalar() as Int32?; if(result.HasValue) { return result.Value; } else { throw new Exception(); // just an example, in my code I throw my own exception }
我希望我可以使用运算符??
像这样:
return command.ExecuteScalar() as Int32? ?? throw new Exception();
但它会生成编译错误。
是否可以重写我的代码,或者只有一种方法可以做到这一点?
对于C#7
在C#7中, throw
成为一个表达式,因此可以完全使用问题中描述的代码。
对于C#6及更早版本
你不能直接在C#6及更早版本中做到这一点 – 第二个操作数是?? 需要是一个表达式,而不是一个抛出语句。
如果您真的只是想找到一个简洁的选项,那么有一些选择:
你可以写:
public static T ThrowException() { throw new Exception(); // Could pass this in }
然后:
return command.ExecuteScalar() as int? ?? ThrowException();
我真的不建议你这样做但是……它非常可怕而且非常不合时宜。
扩展方法怎么样:
public static T ThrowIfNull(this T value) { if (value == null) { throw new Exception(); // Use a better exception of course } return value; }
然后:
return (command.ExecuteScalar() as int?).ThrowIfNull();
又一种替代方案(同样是一种扩展方法):
public static T? CastOrThrow(this object x) where T : struct { T? ret = x as T?; if (ret == null) { throw new Exception(); // Again, get a better exception } return ret; }
致电:
return command.ExecuteScalar().CastOrThrow();
这有点难看,因为你不能指定int?
作为类型参数……
如前所述,你不能用?? 操作员(嗯,不是没有一些似乎不符合你的目标,使这个更清洁)。
当我看到这种模式出现时,我立即想到了Enforcements 。 最初来自C ++世界,他们很好地转移到C#,虽然在大多数时候可以说不那么重要。
这个想法是你采取的forms:
if( condition ) { throw Exception; }
并将其转换为:
Enforce( condition );
(您可以通过默认exception类型进一步简化)。
更进一步,您可以为不同的条件检查编写一组Nunit风格的方法,例如;
Enforce.NotNull( obj ); Enforce .Equal( actual, expected ); Enforce .NotEqual( actual, expected );
等等
或者,更好地通过提供期望lamba:
Enforce( actual, expectation );
真正干净的是,一旦你完成了,你可以返回实际的参数并强制内联 :
return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;
……这似乎与你所追求的最接近。
我之前已经完成了这个实现。 有几个小小的问题,比如你通常如何创建一个带参数的exception对象 – 那里有一些选择(我当时选择了reflection,但是将工厂作为额外参数传递可能会更好)。 但总的来说,它非常简单,可以真正清理很多代码。
这是我要做的事情列表,以打开开源实现。
如果您只想在返回值不是Int32
时发生exception,请执行以下操作:
return (int)command.ExecuteScalar();
如果你想抛出自己的自定义exception,那么我可能会做这样的事情:
int? result = command.ExecuteScalar() as int?; if (result == null) throw new YourCustomException(); return result.Value;
您无法在空合并运算符的右侧抛出exception。 这背后的原因是运算符的右侧需要是表达式,而不是语句。
null合并运算符的工作原理如下:如果运算符的左值为null,则返回它; 否则,返回操作员右侧的内容。 throw
关键字不返回值; 因此,它不能在操作员的右侧使用。
你不能做的原因:
return command.ExecuteScalar() as Int32? ?? throw new Exception();
是因为抛出exception是一种陈述,而不是一种表达。
如果您只是想缩短代码,可能这样:
var result = command.ExecuteScalar() as Int32?; if(result.HasValue) return result; throw new Exception();
不需要别的。