Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以使用运算符??并抛出新异常()?_C#_.net_Nullable_Null Coalescing Operator - Fatal编程技术网

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 brilliant
ThrowIfNull
+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;