【问题标题】:Why do Java and C# not have implicit conversions to boolean?为什么 Java 和 C# 没有到布尔值的隐式转换?
【发布时间】:2011-02-26 11:06:09
【问题描述】:

自从我开始使用 Java 以来,它不支持从数字类型到布尔值的隐式转换,这让我非常恼火,所以你不能这样做:

if (flags & 0x80) { ... }

相反,您必须经历这种疯狂:

if ((flags & 0x80) != 0) { ... }

null 和对象也是如此。我知道的所有其他类 C 语言包括 JavaScript 都允许它,所以我认为 Java 只是愚蠢的,但我刚刚发现 C# 是相同的(至少对于数字,不知道 null/objects): http://msdn.microsoft.com/en-us/library/c8f5xwh7(VS.71).aspx

Microsoft 故意从 C++ 更改它,那为什么呢?显然我错过了一些东西。为什么要改变(我认为是)世界上最自然的事情来延长打字时间?这到底是怎么回事?

【问题讨论】:

  • 这不是疯子,只是不习惯。
  • if (status = CODE_RED) launch_nuclear_missiles();
  • 真正的问题是,为什么像 C 这样的语言允许将隐式转换为布尔值的疯狂:)
  • 这是一个功能,而不是一个错误。
  • 为什么隐式转换应该是默认值? flags & 0x80truefalse 的逻辑概念无关,只是因为true一些 系统上恰好被表示为非零数字。就像声明字符串"0" 也应该代表false 一样是错误的。另一方面,(flags & 0x80) != 0 现在是一个有意义的布尔表达式!

标签: c# java boolean type-conversion


【解决方案1】:

为了清楚起见。它使以下错误简直是非法的:

int x = ...;

if (x = 0)  // in C: assign 0 to x and always evaluate to false 
   ....     // never executed

注意:大多数现代 C/C++ 编译器都会对这种简单的模式给出警告(但不是错误),但可能有许多变化。它可能会爬到你身上。

【讨论】:

  • 理论上,在 C# 中 x 的类型可能实现了从 intbool 的隐式转换运算符,在这种情况下,这将在 C# 中编译。如果您限定 x 是内置数字类型(如 int),那么您的示例绝对正确。
  • @LBushkin,你是对的,我会添加它。但假设自定义转换在这里有点牵强。
  • 许多 Underhanded C 提交的代码中都有这个小栗子。
【解决方案2】:

Java 和 C# 都放弃了对布尔值的隐式转换以减少程序员出错的机会

例如,很多程序员会不小心写:

if( x = 5 ) { ... }

代替:

if( x == 5 ) { ... }

这当然会导致完全不同的行为,因为第一个语句执行赋值(这将始终导致结果为真),而第二个语句执行比较。过去,开发人员有时会反向编写这样的分配以避免陷阱,因为:

if( 5 = x ) { ... } // doesn't compile.

现在,在 C# 中,您仍然可以为您自己的类型创建到 bool 的隐式转换运算符 - 尽管很少建议这样做,因为大多数开发人员并不期望它:

public class MyValue
{
   public int Value { get; set; }

   public static implicit operator bool( MyValue mb )
   {
       return mb.Value != 0;
   }
}

MyValue x = new MyValue() { Value = 10; }
if( x ) { ... } // perfectly legal, compiler applies implicit conversion

【讨论】:

    【解决方案3】:

    也许他们觉得更明确更符合强类型语言。

    【讨论】:

    • 这似乎更像是评论而不是答案
    【解决方案4】:

    你搞错了。
    实际上是 C 不支持boolean,所以if(和任何其他条件语句)实际上期望int 值,而不是boolean。然后 0 的 int 值被视为 false,任何其他值被视为 true

    有些人实际上觉得它有点模棱两可,因为这种行为会导致很多错误,正如其他人所指出的那样。因此,Java 设计人员选择在条件语句中仅支持 boolean 类型。当微软决定实现 MS-Java(又名 C#)时,他们就借鉴了这个设计原则。

    如果你不喜欢,你可以用没有这个限制的多种语言编程。

    【讨论】:

      【解决方案5】:

      任何 int 值(例如 (flags & 0x80))到布尔值的隐式转换意味着语言定义的从 int 值到布尔值的映射。 C 这样做了,并造成了大量的混乱和大量的程序员错误。没有充分的理由说明零 int 值始终意味着真(或假),并且有很多充分的理由说明您可能希望将决定留给程序员。由于这些原因,大多数现代语言都放弃了到布尔值的隐式转换。

      如果你每次做一个小测试都输入七个额外的字符构成“疯狂”,你可能是在错误的职业。如果您非常频繁地在 int 中进行位测试,您可能需要考虑是否过早地进行优化以节省内存。

      【讨论】:

      • 这种“疯狂”是我们有 ++ 运算符的原因,它曾经优化 INCR 指令,但现在只是用作打字快捷方式。
      • 我同意。到布尔值的隐式转换可能很有用,但声明一些任意值是假的,而其他一些同样任意的值是真的不是这样。例如,在 Ruby 和许多 Lisps 中,除了falsenileverything 都是真的。这是一个简单且显而易见的规则。 “有些数字是真的,有些是假的,除非你写自己的数字类型,在这种情况下它们既不是真的也不是假的”并不是一个简单的规则。另外,为什么数字应该是真或假,而不是矩阵?还是Users?
      【解决方案6】:

      即使是最有经验的程序员也会在隐式转换为布尔值时遇到问题。我很欣赏这个小功能。

      【讨论】:

        【解决方案7】:

        一些编程语言根本没有自动强制。例如,一个整数只能与另一个整数进行比较;分配给非整数变量会导致错误。这就是强类型语言的标志。

        Java 执行任何强制转换对您来说都是一种方便,并且打破了强类型模型。

        将整个整数范围——甚至更大范围的浮点数——映射到两个布尔值上,对于“真”和“假”的任意分配充满了分歧。

        • 什么值映射到假和真?如果您是 C,则只有零映射为 false,所有其他值都为 true。如果您是 bash shell,则相反。
        • 应该如何映射负值?

        当您尝试将双精度数自动转换为整数时,Java 将此标记为“精度损失”错误。以此类推,将数字转换为布尔值也会导致精度损失。相反,Java 选择在语法上不支持它。

        【讨论】:

        • 我不知道如何将int 映射到bool。能给个链接吗?
        • 本身没有正式的辩论。但由于某些语言对如何进行转换有不同的想法,因此显然没有标准。
        • 嗯,有一个标准,它的 X86 和 ALU。 True 被评估为非零,并且 false 为零。简单的 ALU '和'指令集。每个人都没有标准,因为它对现代计算机的工作方式至关重要。
        猜你喜欢
        • 2018-02-11
        • 1970-01-01
        • 2021-04-22
        • 2010-11-04
        • 1970-01-01
        • 2018-01-03
        • 1970-01-01
        • 2017-04-11
        • 2015-11-07
        相关资源
        最近更新 更多