C#?:条件运算符

Ioa*_*nis 41 .net c# conditional-operator c#-2.0

我有这个C#2.0源代码的摘录:

object valueFromDatabase;
decimal result;
valueFromDatabase = DBNull.Value;

result = (decimal)(valueFromDatabase != DBNull.Value ? valueFromDatabase : 0);
result = (valueFromDatabase != DBNull.Value ? (decimal)valueFromDatabase : (decimal)0);
Run Code Online (Sandbox Code Playgroud)

第一个结果评估抛出,InvalidCastException而第二个结果评估不抛出.这两者有什么区别?

Eri*_*ert 101

更新:这个问题是我的博客2010年5月27日的主题.谢谢你这个好问题!

这里有很多令人困惑的答案.让我试着准确回答你的问题.让我们简化一下:

object value = whatever;
bool condition = something;
decimal result = (decimal)(condition ? value : 0);
Run Code Online (Sandbox Code Playgroud)

编译器如何解释最后一行?编译器面临的问题是条件表达式类型必须对两个分支都是一致的.语言规则不允许您在一个分支上返回对象而在另一个分支上返回int.选择是object和int.每个int都可以转换为object,但并非每个对象都可以转换为int,因此编译器会选择对象.因此这是一样的

decimal result = (decimal)(condition ? (object)value : (object)0);
Run Code Online (Sandbox Code Playgroud)

因此返回的零是一个盒装的int.

然后将int解包为十进制.将盒装int解包为十进制是非法的.出于这个原因,请参阅我关于该主题的博客文章:

表征和身份

基本上,你的问题是你的行为就好像分配到十进制的转换一样,如下所示:

decimal result = condition ? (decimal)value : (decimal)0;
Run Code Online (Sandbox Code Playgroud)

但正如我们所见,那不是什么

decimal result = (decimal)(condition ? value : 0);
Run Code Online (Sandbox Code Playgroud)

手段.这意味着"将两个替代品都放入对象然后取消生成对象".

  • @Raj:好的,那么编译器应该用b做什么?"":null - 在一个分支上返回一个字符串,在另一个分支上返回无类型的空引用.编译器应该抱怨吗?由于一方甚至没有类型,显然类型不相等. (10认同)
  • @raj:您希望实现什么规则来确定何时给出编译错误? (2认同)
  • @Matthew:您如何使用条件表达式创建合法的C#程序,以便不使用该值? (2认同)

Guf*_*ffa 12

不同的是,编译器不能确定是之间的良好匹配一个数据类型ObjectInt32.

您可以显式地将int值转换object为在第二个和第三个操作数中获取相同的数据类型以便它进行编译,但是couse意味着您正在装箱并取消装箱值:

result = (decimal)(valueFromDatabase != DBNull.value ? valueFromDatabase : (object)0);
Run Code Online (Sandbox Code Playgroud)

那将编译,但不会运行.您必须将十进制值设置为unbox作为十进制值:

result = (decimal)(valueFromDatabase != DBNull.value ? valueFromDatabase : (object)0M);
Run Code Online (Sandbox Code Playgroud)


Dzm*_*uba 5

运算符的类型将是对象,如果结果必须为0,则将隐式装箱.但是默认情况下0 literal是int类型所以你选择int.但是如果使用显式强制转换为十进制,则尝试将其取消包装,这是不允许的(盒装类型必须与您回放的那个相同).这就是为什么你可以得到例外.

以下是C#规范的摘录:

?:运算符的第二个和第三个操作数控制条件表达式的类型.设X和Y是第二个和第三个操作数的类型.然后,

  • 如果X和Y是相同的类型,那么这是条件表达式的类型.
  • 否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型.
  • 否则,如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是条件表达式的类型.
  • 否则,无法确定表达式类型,并发生编译时错误.