我接下来有很多方法:
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();
但它会产生编译错误。
是否可以重写我的代码,或者只有一种方法可以做到这一点?
答案 0 :(得分:54)
对于C#7
在C#7中,throw
成为表达式,因此可以完全使用问题中描述的代码。
对于C#6及更早版本
你不能在C#6及更早版本中直接直接 - 第二个操作数?需要是一个表达式,而不是一个抛出语句。
如果您真的只是想找到一个简洁的选项,那么有一些选择:
你可以写:
public static T ThrowException<T>()
{
throw new Exception(); // Could pass this in
}
然后:
return command.ExecuteScalar() as int? ?? ThrowException<int?>();
我真的不建议你这样做但是......这是非常可怕和单一的。
扩展方法怎么样:
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<T>(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>();
这有点难看,因为你不能指定int?
作为类型参数......
答案 1 :(得分:9)
如前所述,你不能用??操作员(好吧,不是没有一些看起来不符合你的目标的扭曲)。
当我看到这种模式出现时,我立即想到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 );
等
或者,更好地通过提供期望lamba:
Enforce<Exception>( actual, expectation );
真正干净的是,一旦你完成了,你就可以返回实际的参数并强制执行内联:
return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;
......这似乎与你所追求的最接近。
我之前已经完成了这个实现。有一些小问题,比如你通常如何创建一个带参数的异常对象 - 那里有一些选择(我当时选择了反射,但是将工厂作为额外参数传递可能会更好)。但总的来说,这一切都非常简单,可以真正清理很多代码。
这是我要做的事情列表,可以用来打开开源实现。
答案 2 :(得分:4)
如果您只想在返回值不是Int32
时发生异常,请执行以下操作:
return (int)command.ExecuteScalar();
如果你想抛出自己的自定义异常,那么我可能会做这样的事情:
int? result = command.ExecuteScalar() as int?;
if (result == null) throw new YourCustomException();
return result.Value;
答案 3 :(得分:2)
您无法在空合并运算符的右侧抛出异常。这背后的原因是运算符的右侧需要是表达式,而不是声明。
null合并运算符的工作原理如下:如果运算符的左值为null,则返回它;否则,返回操作员右侧的内容。 throw
关键字不会返回值;因此,它不能在操作员的右侧使用。
答案 4 :(得分:1)
你无法做到的原因:
return command.ExecuteScalar() as Int32? ?? throw new Exception();
是因为抛出异常是一种陈述,而不是一种表达。
如果您只是想缩短代码,可能就是这样:
var result = command.ExecuteScalar() as Int32?;
if(result.HasValue) return result;
throw new Exception();
不需要别人。