C# 为什么?:导致转换错误,而if-else没有?
在代码中做一些更改我使用下一行:C# 为什么?:导致转换错误,而if-else没有?,c#,.net,type-conversion,C#,.net,Type Conversion,在代码中做一些更改我使用下一行: uint a = b == c ? 0 : 1; Visual Studio向我显示此错误: 无法将类型“int”隐式转换为“uint”。存在显式转换(是否缺少强制转换?) 但如果我使用代码: uint a; if (b == c) a = 0; else a = 1; 它工作正常,没有任何错误或警告。为什么?您应该使用以下命令使代码正常工作: uint a = b == c ? 0U : 1U; 为什么我不能使用uint a=b
uint a = b == c ? 0 : 1;
Visual Studio向我显示此错误:
无法将类型“int”隐式转换为“uint”。存在显式转换(是否缺少强制转换?)
但如果我使用代码:
uint a;
if (b == c)
a = 0;
else
a = 1;
它工作正常,没有任何错误或警告。为什么?您应该使用以下命令使代码正常工作:
uint a = b == c ? 0U : 1U;
为什么我不能使用uint a=b==c?0 : 1;代码>
表达式的类型b==c?0:1是int
。如中所示,没有从int
到uint
的隐式转换,因此这是不允许的
为什么我可以使用a=0
因为当值是常量表达式时,会对数值类型进行特殊处理
根据C#规范第6.1.9节:
- int类型的常量表达式可以转换为sbyte、byte、short、ushort、uint或ulong类型,前提是常量表达式的值在目标类型的范围内
- long类型的常量表达式可以转换为ulong类型,前提是常量表达式的值不是负值
如第一个项目符号所示,a=0
和a=1
都是允许的,因为0
和1
是常量表达式,并且是有效的uint
值。基本上,这归结为编译器可以在编译时轻松确定这些转换是否有效,因此它允许它们
顺便说一句,如果第一个示例的b==c
部分更改为常量表达式(例如true
),然后整个条件运算符表达式将是一个常量表达式,代码将编译。如果b==c
是一个常量表达式,那么整个条件运算符将被视为一个常量表达式,因此,允许将int
类型的常量表达式转换为其他int类型的规则将适用,并且它将编译
显然,b==c
不是一个常量表达式,因此在运行时之前无法知道条件运算符的结果,因此允许将int隐式转换为uint(对于常量表达式)的豁免不适用
在if
/else
变量中,两个实际赋值都是常量表达式。(b==c)?0U:1U
可以工作。这是由于将整数文本直接赋给变量时发生的隐式转换。但当您使用三元运算符时,编译器不进行隐式转换,只检查两个分支是否可以转换为同一类型。避免此问题的更好方法是首先不使用uint。你为什么要用uint?这在C#中是一种糟糕的代码味道。uint是为了与使用uint的C和COM库的互操作性而存在的。@JakeMillington:此外,如果你的数量经常超过20亿,那就看在上帝的份上使用long。你真的想花一分钟来调试这个问题吗?当你认为永远不到40亿的数量突然变成50亿的时候,uint就结束了?杰克·米林顿:等等,还有更多。假设我们有两个量,它们在逻辑上从不为负。比如说,字符串的大小。好的,我这么说:string.Length
现在是uint
。现在请为我正确地编写代码,它包含两个字符串,并给出它们长度的差异。您认为有多少次会忘记将强制转换添加到int?您认为这个bug需要多长时间才能导致严重故障?现在我们有了一个程序,它在市场上的失败是由于使用了uint!UINT与我们日常工作的数学域不匹配。@JakeMillington:A长是八个字节。整数是四。您至少有20亿字节的地址空间。你有超过一亿的钱吗?如果是这样,那就开始担心吧。你是一个记忆亿万富翁;不用担心便士。这是可行的,但它不能回答OP的问题。这就解释了为什么uint a=true?0:1不编译。要点是隐式转换只适用于常量表达式。@haim770-这就是我决定回答的原因。格罗的评论虽然基本上是充分的,但暗示条件运算符永远不会允许这种情况发生。