这有效:
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?)
为什么我必须对最后两个案例进行演绎,而不是针对前两个案例?
答案 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)在编译时无法解析为常量。因此,编译器将5
和10
视为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
范围内,即-32768
到32767
。
像5
,10
或4
这样的文字在C#中有int
类型(适用于-2147483648
和{{之间的任何整数字面值1}}并且后面没有符号2147483647
,L
或类似符号)。因此,如果我们查看所有作业的右侧,它们显然是U
个表达式,而不是int
。
在short
的情况下,由于10 > 4 ? 5 : 10
和10
是编译时常量,因此4
与true ? 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;
在最后两个语句中,这不是真的,因为您使用变量来保存值而不是常量。编译器不检查变量的实际值,以查看它是否可以将表达式减少为常量。所以你实际上需要施法。