aba*_*hev 28 .net c# nullable null-coalescing-operator
我接下来有很多方法:
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
}
Run Code Online (Sandbox Code Playgroud)
我希望我可以使用这样的运算符??:
return command.ExecuteScalar() as Int32? ?? throw new Exception();
Run Code Online (Sandbox Code Playgroud)
但它会生成编译错误.
是否可以重写我的代码,或者只有一种方法可以做到这一点?
Jon*_*eet 54
对于C#7
在C#7中,throw变成一个表达式,所以可以正确使用问题中描述的代码.
对于C#6及更早版本
你不能直接在C#6及更早版本中做到这一点- 第二个操作数是?? 需要是一个表达式,而不是一个抛出语句.
如果你真的只想找到一个简洁的选项,有几种选择:
你可以写:
public static T ThrowException<T>()
{
throw new Exception(); // Could pass this in
}
Run Code Online (Sandbox Code Playgroud)
然后:
return command.ExecuteScalar() as int? ?? ThrowException<int?>();
Run Code Online (Sandbox Code Playgroud)
我真的不建议你这样做但是......它非常可怕而且非常不合时宜.
扩展方法怎么样:
public static T ThrowIfNull(this T value)
{
if (value == null)
{
throw new Exception(); // Use a better exception of course
}
return value;
}
Run Code Online (Sandbox Code Playgroud)
然后:
return (command.ExecuteScalar() as int?).ThrowIfNull();
Run Code Online (Sandbox Code Playgroud)
又一种替代方案(同样是一种扩展方法):
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;
}
Run Code Online (Sandbox Code Playgroud)
致电:
return command.ExecuteScalar().CastOrThrow<int>();
Run Code Online (Sandbox Code Playgroud)
这有点难看,因为你不能指定int?为类型参数......
如前所述,你不能用?? 操作员(好吧,不是没有一些看起来不符合你的目标的扭曲).
当我看到这种模式出现时,我立即想到了Enforcements.最初来自C++世界,他们很好地转移到C#,虽然大多数时候可以说不那么重要.
这个想法是你采取的形式:
if( condition )
{
throw Exception;
}
Run Code Online (Sandbox Code Playgroud)
并将其转换为:
Enforce<Exception>( condition );
Run Code Online (Sandbox Code Playgroud)
(您可以通过默认异常类型进一步简化).
更进一步,您可以为不同的条件检查编写一组Nunit风格的方法,例如;
Enforce<Exception>.NotNull( obj );
Enforce<Exception>.Equal( actual, expected );
Enforce<Exception>.NotEqual( actual, expected );
Run Code Online (Sandbox Code Playgroud)
等等
或者,更好地通过提供期望lamba:
Enforce<Exception>( actual, expectation );
Run Code Online (Sandbox Code Playgroud)
真正干净的是,一旦你完成了这个,你可以返回实际的参数并强制内联:
return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;
Run Code Online (Sandbox Code Playgroud)
......这似乎与你所追求的最接近.
我之前已经完成了这个实现.有一些小问题,比如你通常如何创建一个带参数的异常对象 - 那里有一些选择(我当时选择了反射,但是将工厂作为额外参数传递可能会更好).但总的来说,这一切都很简单,可以真正清理很多代码.
这是我要做的事情列表,以打开开源实现.
| 归档时间: |
|
| 查看次数: |
8779 次 |
| 最近记录: |