发现一个有趣的问题,即代码运行后会产生不同的结果:
char c = 'a';
c += 'a'; //passed
c = c + 'a'; //Cannot implicitly convert type 'int' to 'char'. An explicit conversion exists (are you missing a cast?)
a += b
和a=a+b
之间有什么区别,或者只是编译器的代码检查错过了吗?
我的观点是char += char
在考虑char = (char+char)
char = int
时可以通过代码检查的原因?
答案 0 :(得分:44)
C# Specification,第7.17.2节复合赋值:
通过应用二元运算符重载决策(第7.3.4节)处理形式
x op= y
的操作,就好像操作是写x op y
一样。然后,...
•否则,如果所选运算符是预定义运算符,则所选运算符的返回类型可明确转换为
x
类型,并且y
可隐式转换为类型x
或运算符是移位运算符,然后将操作评估为x = (T)(x op y)
,其中T
是x
的类型,但评估x
除外只有一次
这正是我们在这里的情况。该操作的返回类型为int
,但x
和y
的类型均为char
,因此会自动为我们插入额外的演员。
(我相信这个规则的存在是因为你无法自己插入一个明确的演员,并且它有点“预期”可行,特别是在x
和y
是相同类型)
答案 1 :(得分:9)
在第二种情况下,失败的是赋值,而不是计算本身。如果你明确地将第二行中的结果转换为char它可以正常工作,实际上以下三行生成相同的IL:
c += (char)1;
c = (char)(c + (char)1);
c = (char)(c + 1);
是的。有区别。
请注意,在第三行中,我没有费心将1
转换为char
,因为计算只会将其转换回int。
答案 2 :(得分:4)
在这种情况下,结果类型+ =是char,结果类型c +(char)1是int。
以下代码打印:
o1 System.Char o2 System.Int32
public static void Main(string[] args)
{
char c = 'a';
object o1 = c += (char)1;
object o2 = c + (char)1;
WriteLine("o1 " + o1.GetType());
WriteLine("o2 " + o2.GetType());
}
答案 3 :(得分:2)
用更简单的术语表达Damien的答案:
复合运算符(例如+=
,-=
等)自动将结果转换为目标类型(如果可能)。
因此c += 'a'
有效,因为它被评估为c = (char)(c + 'a')
。
在这种情况下,转换是必要的,因为字符之间的算术运算的返回类型是int
(这就是c = c + 'a'
无法编译的原因,因为它缺少上面的转换)。