是否可以使用操作员? 并抛出新的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(); 

不需要别的。