在VB.NET中将布尔值转换为整数

37

请看以下代码:

Sub Main()

    Dim i As Integer
    Dim b As Boolean

    i = 1
    b = i
    i = b
    Console.WriteLine(i)

    i = Convert.ToInt32(b)
    Console.WriteLine(i)

End Sub

这将打印以下内容:

-1
1

为什么会这样呢?

(只是个玩笑 :) 你也可以得到0分...

Int32.TryParse("True", i)
Console.WriteLine(i)
8个回答

51
你所看到的是一些旧代码的遗留问题。
问题的核心在于VT_BOOL类型。Visual Basic 6.0使用VT_BOOL类型(也称为VARIANT_BOOL)来表示布尔值。VARIANT_TRUE代表True,其整数值为-1。在转换为.NET时,决定使用Visual Basic转换例程将布尔值转换为整数值时,将保持Visual Basic 6.0语义,即返回值为-1。
第一个隐式转换发生在b = i这一行。实际上进行了从整数到布尔值的隐式转换。任何非零值都被视为true,因此结果为true。
然而,下一行代码正在执行对整数类型的隐式转换。
i = b

在幕后,这使用了Visual Basic转换例程之一(CTypeCInt)将值转换为整数。因此,Visual Basic语义正在发挥作用,返回的值为-1。
下一行有趣的是Convert.ToInt32()行。这是使用.NET转换例程,不使用Visual Basic语义。相反,它返回一个真布尔值的基础BCL表示形式,即1。

4
你可能想要增加一些关于为什么使用VT_BOOL以及为什么它的值是-1的内容。VB 6只有一个逻辑和按位运算符的集合,这两种操作都使用“and”和“or”运算符(大多数语言都有两个集合)。这是通过将“and”实现为“&”,并将文字默认设置为-1来实现的。 - Scott Wisniewski
这样,“true and x”只要“x”非零,就是非零的。 - Scott Wisniewski
你可以在我回答一个大部分无关的问题的链接中了解到我的回答的“为什么”:https://stackoverflow.com/a/46331671/3043 - Joel Coehoorn
这句话是如何解释编译器为什么会将bool转换为int:-(b > false) - Isaac Kleinman

33

有些语言将布尔值 true 视为 -1 而不是 1。我需要进行研究才能弄清原因,因为我不记得了。

在 VB6 中,常量 True 的值为 -1

然而,Convert.ToInt32(Boolean) documented 的返回值为 "如果 value 为 true,则为数字 1;否则为 0。" 这样,无论使用哪种框架语言,它都是相同的。

编辑:参见问题 boolean true -- positive 1 or negative 1


1
有些编程语言使用-1作为True,因为它是0b11111111,所以每个位都是零的二进制表示的相反数,这样在一个位取反操作上使用一个会导致另一个。 - mbomb007
1
在.NET 4.0中,您可以得到CInt(true) = -1Convert.Int32(true) = 1 - Pato

12

为什么要使用-1来表示True,我认为是因为它的字面意思是(NOT 0)。

从零开始,翻转所有位,然后按二进制补码读取——结果就是负一。

因此,由于任何不是False的东西都是True,而False是0,所以(NOT False)用-1来表示。

尽管这可能只是巧合....


4
这正是为什么 VB 使用 -1 表示 True 的原因。 :) - Daniel Lo Nigro
1
有趣的是,如果“true”为-1,则可以使用相同的运算符进行布尔逻辑和整数位掩码操作。同样有趣的是,“and”和“or”是否短路的问题与是否将“true”操作数强制为单个值的问题无关。 - supercat

8

来自 MSDN Visual Basic 文档:

类型转换

当 Visual Basic 将数值数据类型转换为布尔型时,0 变成 False,而其他所有值变成 True。当 Visual Basic 将布尔型值转换为数值类型时,False 变成 0,True 变成 -1。

对于 Convert.ToInt32(value):

如果 value 为 true,则返回数字 1;否则返回 0。

因此,在您的代码中:

i = 1
b = i // b becomes true
i = b // true = -1
Console.WriteLine(i)  // i is -1

i = Convert.ToInt32(b)  // Convert.ToInt32(true) = 1
Console.WriteLine(i)    // i is 1

请添加文档引用的链接,我会点赞支持。 - Joel Coehoorn

3

这是因为在VB.NET中,布尔值默认为-1表示真,0表示假。虽然我不确定为什么第二次会打印为1...


2
“True”是从数值数据类型的0值取反得到的!对于非有符号类型,Not(0)返回1。对于有符号类型,Not(0)返回-1。我不知道你的代码,也许你的代码在第二次执行时进行了内部数据转换。

2

这个答案有些靠不住,但是:

    Dim b As Boolean
    b = False
    Dim i As Integer
    i = IIf(b, 1, 0)

1

所有数值数据类型都可以用作布尔类型!结果取决于所使用的数据类型。

例如:

Dim i As Byte    ' Byte is non-signed!
Dim b As Boolean = True

i = b            ' Set first (lowest) bit of i (non-signed byte)
' i is now binary 0000 0001 = 1!


Dim i As SByte   ' SByte is signed!
Dim b As Boolean = True

i = b            ' Set all bits of i (signed byte)
' i is now FF (binary 1111 1111 = -1 !

整数是有符号的,True 转整数 -> -1。

UInteger 是无符号的,True 转 UInt -> 1。

等等...

False 值会清除有符号数字中的最高位,在无符号数字中则清除最低位。

因此,False 在所有数值数据类型中都是 0。


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