【问题标题】:Why does ?: cause a conversion error while if-else does not? [duplicate]为什么 ?: 会导致转换错误,而 if-else 不会? [复制]
【发布时间】:2017-07-30 03:03:00
【问题描述】:

对代码进行一些更改,我使用下一行:

uint a = b == c ? 0 : 1;

Visual Studio 向我显示此错误:

无法将类型“int”隐式转换为“uint”。存在显式转换(您是否缺少演员表?)

但是如果我使用代码:

uint a; 

if (b == c) 
    a = 0; 
else 
    a = 1;

它可以正常工作,没有任何错误或警告。为什么?

【问题讨论】:

  • (b == c) ? 0U : 1U 可以。这是由于直接分配给变量时整数文字发生的隐式转换。但是当你使用三元运算符时,编译器不会进行隐式转换,只会检查两个分支是否可以转换为相同的类型。
  • 避免此问题的更好方法是首先不使用 uint。你为什么使用uint?这是 C# 中不好的代码气味。 uint 用于与使用 uint 的 C 和 COM 库进行互操作。
  • @JakeMillington:此外,如果您的数量通常超过 20 亿,那么看在上帝的份上,请使用 long。当你认为总是小于 40 亿的数量突然变成 50 亿,并且 uint 换行时,你真的要花一分钟调试问题吗?
  • @JakeMillington:但是等等,还有更多。假设我们有两个逻辑上永远不会为负的量。例如,字符串的大小。好的,我这么说:string.Length 现在是uint。现在请正确地为我编写接受两个字符串并给出它们长度差异的代码。您认为您多久会忘记将演员表添加到 int 中?您认为该错误会导致严重故障需要多长时间?现在我们有了一个程序,它在市场上的失败是由于使用了 uint! uint 与我们日常工作的数学领域不匹配。
  • @JakeMillington:long 是 8 个字节。一个 int 是四。您至少有 20 亿字节的地址空间。你有超过一亿多头吗?如果是这样,那就开始担心它。你是记忆亿万富翁;不用担心一分钱。

标签: c# .net type-conversion


【解决方案1】:

为什么我不能使用uint a = b == c ? 0 : 1;

表达式b == c ? 0 : 1 的类型是int。如this table所示,从intuint没有隐式转换,所以这是不允许的。

为什么我可以使用a = 0

因为当值是常量表达式时,数值类型有特殊处理。

来自 C# 规范的第 6.1.9 节:

  • 如果常量表达式的值在目标类型的范围内,则可以将 int 类型的常量表达式转换为 sbyte、byte、short、ushort、uint 或 ulong 类型。

  • long 类型的常量表达式可以转换为 ulong 类型,前提是常量表达式的值不是负数。

如第一个项目符号中所示,a = 0a = 1 都是允许的,因为 01 是常量表达式并且是有效的 uint 值。基本上,这归结为编译器可以在编译时轻松确定这些转换是有效的,因此它允许它们。

顺便说一句,如果您的第一个示例中的 b == c 部分更改为常量表达式(例如 true),那么整个条件运算符表达式将是一个常量表达式并且代码将编译。

【讨论】:

    【解决方案2】:

    如果 b==c 是一个常量表达式,那么整个条件运算符将被视为一个常量表达式,因此,允许将int 类型的常量表达式转换为其他 int 的规则types 将适用,它会编译。

    显然,b==c 不是常量表达式,因此条件运算符的结果要到运行时才能知道,因此允许将 int 隐式转换为 uint(对于常量表达式)的豁免不适用。

    在您的if/else 变体中,两个的实际赋值都是常量表达式。

    【讨论】:

    • 这解释了为什么uint a = true ? 0 : 1 确实 编译。它的要点是隐式转换仅适用于常量表达式。
    • @haim770 - 这就是我决定回答的原因。 Groo 的评论虽然很充分,但暗示条件运算符永远不会允许它工作。
    【解决方案3】:

    您应该使用literals 来使您的代码正常工作,如下所示:

    uint a = b == c ? 0U : 1U;
    

    【讨论】:

    • 这可行,但不能回答 OP 的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    相关资源
    最近更新 更多