C#无法将布尔值转换为整数

44

我们都知道在C#中无法将bool类型强制转换为int类型。我想使用位掩码查看true的二进制表示,但是我不能使用(bool & int)。我认为问题在于架构设计上的决策:"true即为真,不是任何不等于0的数字"(C++),我想知道这种架构的好处是什么?C语言中的true/false概念有什么问题吗?


2
请参见"问题标题中是否应包含“标签”?",共识是“不应该”! - user57508
10个回答

30

在编程中,如果一个整数不能表示为truefalse,那么对于程序员来说会更加清晰明了。

if (5 > 0)if(5)更易于理解。

这也是为什么在switch语句中不允许“穿透”条件。因为这样太容易出错了。


16
我实际上非常不喜欢C#中switch语句的case穿透方式。有很多情况下,穿透是非常有用的。 - Joseph
8
@Joseph: 最不容易出错的情况仍然被允许——你可以穿过它,只要你在这之前没有做任何工作。但是,在完成其他“工作”后再跳过一个情况是不容易维护的。 - Reed Copsey
2
@Joseph:有用并不意味着它没有错误,或者不容易出错。 - Fredrik Mörk
@Joseph,我认为问题不在于他们防止理解它的工作方式。我认为他们只是试图阻止人们犯错,主要是忘记在case结尾处放置break语句。我同意你的观点,在某些情况下使用它会很有帮助,但有时也会让人感到有些沮丧,但我敢打赌,不能使用它比能使用它更多地挽救了我的错误。 - kemiller2002
对于程序员来说,显式转换比隐式转换更清晰明了。例如在byte的情况下,显式转换已经足够好了。此外,它还可以极大地简化某些情况,例如不等比较器实现:return (int)rBool - (int)lBool; // 此外,它还可以允许微小的优化,避免条件语句(条件语句可能会重置处理器的指令传送带)。 - Krypt
显示剩余5条评论

25
在C中,整数经常被双重用作普通数字和布尔值,例如在while循环中使用某个数字不为零。这是一种清晰明了、简洁的代码编写方式,例如一个天真的strlen例程:
const char *s;
for (s = str; *s; ++s)
    ;
return (s - str);

虽然这样写很简洁,但是它掩盖了代码片段的真实目的,其实本质上是“当我查看的字符不是空字符时循环”。可是书写的时候它只是说“在某些情况下将其视为布尔值,而在其他情况下将其视为数字”。

这种双重性质据称经常会导致问题,使代码难以阅读(因为您必须从上下文中判断所使用的 int 是用作int还是bool)。

如果你确实需要将布尔值用作整数,你可以使用

Convert.ToInt32(someBool)

Noldorin提到的,或者你可以自己来实现。


someBool ? 1 : 0

这两个都清楚地表明你正在使用一个int(而不是bool)。


三元运算符速度较慢。Bool 是数字类型,应该可以转换为用于算术运算。 - Mark Lauter

20

仅供参考,Convert.ToInt32(fooBool) 的结果会告诉你,true 表示为1,而 false 则为0。(这是BCL中的任意表示法,并不一定是在内存中使用的表示法。)

关键在于,位表示法对于任何程序员来说都应该是无意义的。布尔类型应该只用于特定的目的(即标志),不应与int混用,否则变量的使用可能会变得非常混乱。


5

我们可以使用Convert.ToInt32,它的定义如下:

public static int ToInt32(bool value);

5
我认为问题并不是真/假或1/0的问题,而是决定将C#作为强类型语言而不是弱类型语言的问题。 一种编程语言强类型化有许多好处(以及一些缺点)。 其中一个好处是减少由于表达式的误用(或错误使用)而导致的错误。
例如,
int i = 0;
if (i = 1) {
   ...
}

这段代码在C#中甚至无法编译通过,但在C语言中虽然可以编译通过,但执行结果是错误的。

选择将C#作为强类型语言,给C#程序员带来了这些好处。即便如此,如果他们选择,也可以引入从bool到int(以及相反)的转换。我猜想他们没有这样做是因为可能会引入上述代码中的bug。


1
这与“强类型”无关。 在C语言中,if (i=1)是可能的,因为赋值运算符返回一个值(如果您想要执行a = b = c = 5时很有用)。例如,Python是强类型的,并且赋值是一种语句,不会“返回”任何内容。因此,像“if a = 3:”这样的操作是错误的。 但是,Python本身有一个规则,即“任何东西都有布尔解释”:空集合、0、空字符串为False,其他任何东西为True,因此您可以执行以下操作: mylist = [] if mylist: something - ZeD
1
是的,但它允许在此上下文中使用赋值结果的原因是因为它是弱类型的。几乎可以确定意图是 i == 1,这是一个布尔结果,在C#中允许在该上下文中使用。如果C语言是强类型的,那么在这种情况下将不允许使用赋值的结果,就像在C#中一样。由于它是松散评估的布尔值,因此产生了错误(在这种情况下)。 - tvanfosson

3

没有人喜欢受到其他实体的所有决策... 只需编写自己的转换器(快速且草率)


0
var n = (bool)your_int ? 1 : 0

你的回答可以通过提供额外的支持信息来改进。请[编辑]以添加更多细节,例如引用或文档,以便其他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

-1

int n = (bBool) ? 1 : 0


10
我差点要给你的帖子点个踩,因为你用了匈牙利命名法,太难看了! - jpierson

-2

你提出了一个很好的观点。然而,它确实消除了一种捷径。

使用 C 语言可以轻松地通过代码 "bBool = 1 - bBool" 切换开关。

如果 bBool 是真(1),那么 1-1=0,bBool 变为 false。

如果 bBool 是假(0),那么 1-0=1,bBool 变为 true。

而在 C# 中,我需要进行条件判断来检查状态,然后将其设置为相反的状态,这会给机器和我自己带来更多的工作。


18
我漏掉了什么吗?bBool = !bBool; 不就是你描述的功能吗? - Mark A. Donohoe

-3

使用 number != 0,容易出现错误。

C# 做了很多设计决策来避免这种常见错误的发生。


不确定你的观点是什么。也许你可以再详细阐述一下。 - jpierson
通过不允许<code>if (27)</code>这样的语句,编程语言迫使人们使用更可靠的语法,如:<code>if (27 > 0)</code>。 - Peter Drier
啊,我现在明白了,“number 1=0”是原帖中的直接片段。也许在你的回答中加入更多上下文会帮助读者理解你的观点。以它目前的形式来看,它本身并没有意义。通常最好在你的回答中包含一些原始问题的形式,它不需要是直接引用,而是对原始问题的重新表述。 - jpierson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接