在String.Equals中使用C#ternary

时间:2014-08-01 14:38:03

标签: c# .net

这有效:

short value;
value = 10 > 4 ? 5 : 10;

这有效:

short value;
value = "test" == "test" ? 5 : 10;

这不起作用:

short value;
string str = "test";
value = "test" == str ? 5 : 10;

这两个都没有:

short value;
string str = "test";
value = "test".Equals(str) ? 5 : 10;

最后两种情况我收到以下错误:

Cannot implicitly convert type 'int' to 'short'.
An explicit conversion exists (are you missing a cast?)

为什么我必须对最后两个案例进行演绎,而不是针对前两个案例?

4 个答案:

答案 0 :(得分:44)

short value;
value = 10 > 4 ? 5 : 10;             //1
value = "test" == "test" ? 5 : 10;   //2
string str = "test";
value = "test" == str ? 5 : 10;      //3
value = "test".Equals(str) ? 5 : 10; //4

最后两个三元表达式(3,4)在编译时无法解析为常量。因此,编译器将510视为int文字,整个三元表达式的类型为int。要从int转换为short,需要进行显式转换。

前两个三元表达式(1,2)可以在编译时解析为常量。常量值是int,但编译器知道它适合short,因此不需要任何转换。

为了好玩,试试这个:

value = "test" == "test" ? 5 : (int)short.MaxValue + 1;

答案 1 :(得分:4)

您需要使用强制转换才能使最后两个示例正常工作

value = (short)("test" == str ? 5 : 10);

为什么你不需要在前两个?

因为前两个是编译时常量。编译器能够将10 > 4 ? 5 : 10翻译为true ? 5 : 10,然后翻译为5

所以当你写

value = 10 > 4 ? 5 : 10;

它实际上与

相同
value = 5;

编译,因为如果允许编译器在允许的范围内,则允许隐式转换常量。

相反,"test" == str ? 5 : 10;不是编译时常量,因此不允许编译强制转换它。你需要做一个明确的演员你好。

答案 2 :(得分:3)

当然,这是由C#语言规范定义的。

要注意的关键是,从 int short有两种转换。一个是显式转换,它始终适用,但要求您在(short)表达式之前明确地编写int。另一个是 implicit constant expression conversion ,仅当(a) int表达式是编译时才适用常量和(b)此编译时表达式的值在short范围内,即-3276832767

5104这样的文字在C#中有int类型(适用于-2147483648和{{之间的任何整数字面值1}}并且后面没有符号2147483647L或类似符号)。因此,如果我们查看所有作业的右侧,它们显然是U个表达式,而不是int

short的情况下,由于10 > 4 ? 5 : 1010是编译时常量,因此4true ? 5 : 10之间的>运算符相同{1}}是内置的,当操作数是常量时将导致一个常量。并且以int给出true ? 5 : 10的方式相同,因为所有三个操作数都是常量,并且5在这种情况下被归类为常量。所以它真的说:

?:

其中“short value = 5; ”是编译时常量。因此,在编译时检查5 int是否在范围内(与5无关,可能是10),因此在这种情况下,隐式常量表达式转换适用,并且它是合法的。

请注意,您可以执行以下操作:

999999

只要所有操作数都是const int huge = 10; const int tiny = 4; const int significant = 5; const int unimporatnt = 10; short value; value = huge > tiny ? significant : unimportant; 变量(双关语)。

现在,如果我设法明确说明,您现在也知道妨碍const工作的障碍是您没有将value = "test" == str ? 5 : 10;本地标记为str 。这样做,它将被允许。

通过const电话,情况有点糟糕。调用Equals的结果从不被视为编译时常量(并且我认为它不会被“优化”,例如Equals实际上会在运行时调用该方法) 。 "same".Equals("same")(10).Equals(4)等也会发生同样的事情,所以字符串在这方面并不特别。


很可能你已经知道

(10).CompareTo(4) > 0

是不允许的,因为short value = cond ? 5 : 10; 不是编译时常量,而只是使用显式转换,所以写:

cond

或:

short value = cond ? (short)5 : (short)10;

从技术上讲,它们并不相同,因为第一个在运行时没有缩小转换(表达式short value = (short)(cond ? 5 : 10); (short)5(short)10类型的文字),而最后一个一个人必须在运行时将short转换为int(这当然比便宜得便宜)。


其他(未删除的!)答案是正确的,这只是奖励信息。

答案 3 :(得分:2)

问题是10 > 4 ? 5 : 10;实际上在编译时转换为常量,然后才需要进行任何类型转换。这意味着编译器意识到即使在编译需要任何隐式类型转换之前,turnary语句实际上也可以简化为常量。换句话说,表达式与:

相同
value = 5;

在最后两个语句中,这不是真的,因为您使用变量来保存值而不是常量。编译器不检查变量的实际值,以查看它是否可以将表达式减少为常量。所以你实际上需要施法。