C# 是否可以使用运算符??并抛出新异常()?
接下来我有很多方法:C# 是否可以使用运算符??并抛出新异常()?,c#,.net,nullable,null-coalescing-operator,C#,.net,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 } 我希望我能像这样使用操作符??: return command.ExecuteScalar() as
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<T>()
{
throw new Exception(); // Could pass this in
}
然后:
还有另一种选择(同样是一种扩展方法):
publicstatict?卡斯特罗(该对象x)
其中T:struct
{
T?ret=x为T?;
if(ret==null)
{
抛出新异常();//再次获取更好的异常
}
返回ret;
}
致电:
return command.ExecuteScalar().CastOrThrow<int>();
return命令.ExecuteScalar().castorhrow();
这有点难看,因为您不能指定int?
作为类型参数…如果您只是希望在返回值不是Int32
时出现异常,请执行以下操作:
return (int)command.ExecuteScalar();
如果您想抛出自己的自定义异常,那么我可能会执行以下操作:
int? result = command.ExecuteScalar() as int?;
if (result == null) throw new YourCustomException();
return result.Value;
您将无法在null合并运算符的右侧抛出异常。这背后的原因是运算符的右侧需要是表达式,而不是语句
null合并操作符的工作原理如下:如果操作符的左值为null,则返回它;否则,返回运算符右侧的内容。throw
关键字不返回值;因此,它不能在操作员的右侧使用。您不能这样做的原因:
return command.ExecuteScalar() as Int32? ?? throw new Exception();
因为引发异常是一个语句,而不是表达式
如果您只是想将代码缩短一点,可能是这样的:
var result = command.ExecuteScalar() as Int32?;
if(result.HasValue) return result;
throw new Exception();
不需要其他人。正如前面所说,你不能用??接线员(嗯,不是没有一些扭曲,似乎不适合你的目标,使这个清洁)
当我看到这种模式出现时,我立刻想到了。最初从C++世界中,他们转移到C很好,虽然可以说是不太重要的大部分时间。
我们的想法是你采取以下形式:
if( condition )
{
throw Exception;
}
并将其转换为:
Enforce<Exception>( condition );
。。。这似乎是最接近你的目标
我以前已经完成了这项工作。这里有几个小问题,比如如何一般地创建一个接受参数的异常对象——这里有一些选择(当时我选择了反射,但将工厂作为额外参数传入可能更好)。但总的来说,它非常简单,可以真正清理大量代码
这是我要做的事情清单,以推动开源实现。是的,将引发异常。但可能无效的强制转换异常不是要抛出的适当异常;如果该命令不返回值,则可能需要存在特定于应用程序的异常。@Adam:我真的认为不值得投反对票!问题中的示例代码抛出一个普通的异常
。InvalidCastException
或NullReferenceException
比没有额外细节的普通异常更合适、信息更丰富;如果命令不返回值,则可能需要抛出特定于应用程序的异常(例如,norecordseListException
)(是的,我知道海报上没有提到这样的事情,但有些人确实从他们的问题中删除了这样的特殊性),你必须将你发布的语句包装在一个try
/catch
块中,这会破坏压缩代码的目的。@Adam:没错,但是如果没有OP的进一步信息,我要重申,我的代码比问题中的代码更简单,并抛出信息更丰富/更合适的异常。如果这不是OP要求的,那么他们应该在问题中澄清。我喜欢这样。怎么样:试试{return(int)command.ExecuteScalar();}catch{throw new NotFoundException();}这只在这个return语句所在的函数返回一个对象时起作用。任何其他返回类型都会导致编译器错误,因为null合并运算符的左表达式类型和右表达式类型是不同的类型。我删除了答案中的这一部分。我更喜欢反转检查值,如果没有值就抛出。听起来更符合逻辑。我想是因为你回答的不是托尼。不管怎样,我为你反击了。在这里,您的思路是正确的,但是我想有一种更好的、通用的技术,我将添加作为我自己的回答(冒着被否决的风险)Jon,您可以使用通用参数约束创建两个Castorhrow
方法,一个用于值类型/结构,一个用于引用类型吗?前者将使用T?
,而后者将使用T
@Adam:不幸的是,您不能有两种方法,它们的签名的唯一区别是输出类型和/或泛型约束。扩展方法!Simply brilliantThrowIfNull
+1Hi@JonSkeet您可能希望更新此答案,并提示(在C#7中)添加了“做OP想做的事”的功能:有没有理由不在此处使用扩展方法?“return(command.ExecuteScalar()作为int?).exforce(x=>x.HasValue);”对我来说读起来稍微好一点。。。尽管在那一点上更改名称可能是值得的。我确实喜欢使用谓词的想法。主要是因为当我第一次在C中这样做时,我使用的是C#2;-)我没有用lambda fo
return command.ExecuteScalar() as Int32? ?? throw new Exception();
var result = command.ExecuteScalar() as Int32?;
if(result.HasValue) return result;
throw new Exception();
if( condition )
{
throw Exception;
}
Enforce<Exception>( condition );
Enforce<Exception>.NotNull( obj );
Enforce<Exception>.Equal( actual, expected );
Enforce<Exception>.NotEqual( actual, expected );
Enforce<Exception>( actual, expectation );
return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;