为啥 Java 和 C# 没有到布尔值的隐式转换?

Posted

技术标签:

【中文标题】为啥 Java 和 C# 没有到布尔值的隐式转换?【英文标题】: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 现在是一个有意义的布尔表达式! 【参考方案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 '和'指令集。每个人都没有标准,因为它对现代计算机的工作方式至关重要。

以上是关于为啥 Java 和 C# 没有到布尔值的隐式转换?的主要内容,如果未能解决你的问题,请参考以下文章

为啥首先允许指针从非常量到常量的隐式转换?

为啥允许从 int 到 byte 但不允许从 long 到 int 的隐式缩小转换?

为啥“as”运算符在 C# 中不使用隐式转换运算符?

25.scala的隐式转换

Objective-C 对象字面量的隐式布尔转换总是计算为真 ios

为啥从 <T> 到 <U> 的隐式转换运算符接受 <T?>?