是否可以使用运营商?并抛出新的异常()?
-
21-09-2019 - |
题
我有许多方法做下一:
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和更早 - 的第二操作数??需要是一个表达式,而不是一个throw语句。
有几个选择,如果你真的只是想找到一个选项是简洁:
您可以这样写:
public static T ThrowException<T>()
{
throw new Exception(); // Could pass this in
}
然后:
return command.ExecuteScalar() as int? ?? ThrowException<int?>();
我的真正的不建议你这样做,虽然...这是很可怕的,unidiomatic。
如何扩展方法:
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?
作为类型参数这有点难看......
其他提示
正如人们所说的,你不能用做这个?操作(当然,不是没有一些扭曲,似乎并不适合你做这个清洁的目的)。
当我看到这个图案新兴我立即想到强制执行的。最初从C ++世界它们转移到C#相当好,虽然可以说是较不重要的大部分时间。
我们的想法是,你采取的形式的东西:
if( condition )
{
throw Exception;
}
和将其转换为:
Enforce<Exception>( condition );
(可以进一步通过默认异常类型简化)。
以它进一步可以编写的一组NUnit的风格的方法不同的条件检查,e.g;
Enforce<Exception>.NotNull( obj );
Enforce<Exception>.Equal( actual, expected );
Enforce<Exception>.NotEqual( actual, expected );
等
或者,通过提供一种期望兰巴还更好地:
Enforce<Exception>( actual, expectation );
什么是真正整洁的是,一旦你这样做,你可以返回的的实际的PARAM和实施的在线的:
return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;
...这似乎是最接近你追求的。
我之前敲了这方面的一个实现。有一对夫妇的小niggles的,怎么样,你一般创建例外对象,接受参数 - 有一些选择(我选择反射的时间,但作为一个额外的参数传递一个工厂可能会更好)。但总的来说这一切都非常简单,能真正清理了大量的代码。
这是我对事物的名单上做敲了一个开源实现。
如果你只是想要一个异常时,返回的值不是Int32
然后做到这一点:
return (int)command.ExecuteScalar();
如果你想抛出自己的自定义异常,然后我可能会做这样的事情,而不是:
int? result = command.ExecuteScalar() as int?;
if (result == null) throw new YourCustomException();
return result.Value;
你不是要能够扔在空合并运算符右侧的一个例外。这背后的原因是,操作者的右侧需要是一个表达式,而不是一个语句。
空合并操作符如下所示:如果操作者的左值为空,返回它;否则,返回什么是对操作者的权利。该throw
关键字不返回一个值;因此,它不能在运算符右侧的使用。
你不能这样做的原因:
return command.ExecuteScalar() as Int32? ?? throw new Exception();
时因为抛出异常是一个语句,而不是一个表达式。
如果你只是希望缩短代码一点点,也许这样的:
var result = command.ExecuteScalar() as Int32?;
if(result.HasValue) return result;
throw new Exception();
没有必要的东西。