【问题标题】:Convert Boolean to Integer in VB.NET在 VB.NET 中将布尔值转换为整数
【发布时间】:2009-04-13 20:35:12
【问题描述】:

取以下代码:

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)

【问题讨论】:

    标签: vb.net


    【解决方案1】:

    您看到的是一些遗留代码。

    问题的核心是 VT_BOOL 类型。 Visual Basic 6.0 使用 VT_BOOL 类型 (AKA VARIANT_BOOL) 作为其布尔值。 VARIANT_BOOL 的 True 用具有整数值 -1 的值 VARIANT_TRUE 表示。在转换到.NET 的过程中,决定当使用 Visual Basic 转换例程将布尔值转换为整数值时,返回值将保持 Visual Basic 6.0 语义;应该是 -1。

    第一次隐式转换发生在 b = i 行。在引擎盖下,它执行了从整数到布尔值的隐式转换。任何非零值都被认为是真的,因此结果值是真的。

    但是,以下代码行正在隐式转换为整数类型。

    i = b
    

    在后台,它使用 Visual Basic 转换例程之一(CTypeCInt)将值转换为整数。因此,Visual Basic 语义正在发挥作用,返回的值为 -1。

    下一个有趣的行是Convert.ToInt32() 行。这是使用不使用 Visual Basic 语义的 .NET 转换例程。相反,它返回底层 BCL 表示的真正布尔值 1。

    【讨论】:

    • 您可能想要添加一些关于为什么使用 VT_BOOL 以及为什么它的值为 -1 的信息。 VB 6 只有一组“and”和“or”运算符,它们同时进行逻辑和按位运算(大多数语言有 2 组)。这通过将“and”实现为“&”并将字面默认值为 -1 来实现。
    • 这样,只要“x”不为零,“true and x”就不为零。
    • 您可以在我对一个几乎不相关的问题的回答中了解“为什么”:stackoverflow.com/a/46331671/3043
    • 这如何解释为什么编译器似乎这样做是为了将 bool 转换为 int:-(b > false)
    【解决方案2】:

    有些语言认为 boolean true 是 -1 而不是 1。我必须研究一下为什么,因为我不记得了。

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

    但是,Convert.ToInt32(Boolean)documented,因为返回“如果值为 true,则返回数字 1;否则,返回 0。”这样,无论您使用哪种框架语言,它都是一样的。

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

    【讨论】:

    • 有些语言使用-1作为True,因为它是0b11111111,所以每一位都与零的二进制表示相反,因此对一个使用按位非运算会导致其他。
    • 在 .NET 4.0 中你会得到 CInt(true) = -1Convert.Int32(true) = 1
    【解决方案3】:

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

    从零开始,翻转所有位,然后将其作为二进制补码读取——结果为负一。

    因此,既然任何不为 False 的都是 True,而 False 为 0,则 (NOT False) 由 -1 表示。

    不过,这可能只是巧合......

    【讨论】:

    • 这正是 VB 使用 -1 表示 True 的原因。 :)
    • +1。有趣的是,如果“true”为 -1,则相同的运算符可用于布尔逻辑和整数位掩码。值得注意的是,是否短路“and”和“or”的问题与是否应该将“true”操作数强制为单个值的问题无关。
    【解决方案4】:

    来自 MSDN Visual Basic 文档:

    Type Conversions

    当 Visual Basic 转换数字时 数据类型值为 Boolean,0 变为 False 和所有其他值变为 真的。当 Visual Basic 转换 布尔值到数值类型,False 变为 0,True 变为 -1。

    对于Convert.ToInt32(value)

    如果值为真,则返回数字 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
    

    【讨论】:

    • 为这些文档引用添加一个链接,我会升级。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      “真”是数字数据类型的 0 值的否定!

      Not(0) 对于无符号类型返回 1。

      Not(0) 对于有符号类型返回 -1。

      我不知道你的代码,也许你的代码第二次执行内部数据转换。

      【讨论】:

        【解决方案7】:

        这是一个狡猾的答案,但是:

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

        【讨论】:

          【解决方案8】:

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

          例子:

          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 !
          

          整数有符号,整数为真 -> -1。

          UInteger 是无符号的,对 UInt 为真 -> 1。

          等等……

          假值清除有符号数字中的最高位,以及无符号数字中的最低位。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-03-02
            • 2013-12-03
            • 1970-01-01
            • 2014-09-03
            • 1970-01-01
            • 2016-11-28
            • 2012-06-03
            • 1970-01-01
            相关资源
            最近更新 更多