将布尔值转换为整数会返回-1表示true?

时间:2010-09-01 18:30:08

标签: vb.net boolean

我正在使用一些VB.NET代码,这些代码似乎是使用CInt(myBoolean)将一个布尔值转换为整数。发生的奇怪事情是,如果值为true,则返回-1。例如:

CInt(True)  // returns -1
CInt(False) // returns 0

这在其他语言中常见吗?

我认为布尔值如果为真则为1,如果为假则为0。另外,有没有办法让Visual Basic将1赋值为true而不是赋值-1?

9 个答案:

答案 0 :(得分:37)

通常,值false表示为0,值true表示任何非0整数值。 true和false(以及其他)的具体值是您不应该依赖的东西 - 它们可能是特定于实现的。我不确定你要做什么,但最好不要依赖TrueFalse具有任何特定的整数值,除非你绝对不得不这样做。

我可以找到针对VB特定行为的最佳解释来自Wikipedia

  

布尔常量True的数值为-1。这是因为布尔数据类型存储为16位有符号整数。在此构造中,-1计算为16个二进制1(布尔值为True),0为16 0(布尔值为False)。当对16位有符号整数值0执行Not运算时,这将显而易见,该值将返回整数值-1,换句话说,True = Not False。当对整数的各个位执行逻辑运算时,这种固有功能变得特别有用,例如And,Or,Xor和Not。[4]自20世纪70年代早期的Microsoft BASIC实现以来,True的定义也与BASIC一致,并且还与当时CPU指令的特性有关。

答案 1 :(得分:13)

最初使用的解决方法是:

 Dim i As Integer = CInt(Int(False))

这将返回0。

 Dim i As Integer = CInt(Int(True))

这将返回1。

答案 2 :(得分:9)

这似乎是一个陷阱,我不知道这种行为的任何其他例子。

http://msdn.microsoft.com/en-us/library/ae382yt8.aspx指定了这种行为,并带有“不要那样做,mkay”的评论。请进一步说明:

框架中的转换

System命名空间中Convert类的ToInt32方法将True转换为+1。

如果必须将布尔值转换为数字数据类型,请注意您使用的转换方法。

答案 3 :(得分:5)

MSDN documentation提供了一些有价值的见解:

  

布尔值不作为数字存储,并且存储的值不等于数字。您永远不应该编写依赖于True和False的等效数值的代码。只要有可能,您应该将布尔变量的使用限制为它们的设计逻辑值。

答案 4 :(得分:5)

我遇到了同样的问题并在结果上使用了Math.Abs函数:)

答案 5 :(得分:4)

1970年代和1980年代的许多BASIC版本都使用ANDOR运算符实现了逐位算术运算,并将真正的条件表达式求值为-1(这是“所有位 - 设定值)。我不确定为什么决定让真正的条件表达式求值为全位设置值;能够使用AND来掩盖一个条件表达式的整数可能比乘法更快,但鉴于解释器的内部机制,差异可能很小。

在任何情况下,Microsoft为PC生成的BASIC的第一个版本遵循以下条件:具有真正条件的传统评估为-1(全位设置);因为QuickBASIC反过来应该与那些兼容,并且Visual Basic应该与QuickBASIC兼容,所以它们使用相同的表示。尽管.Net将整数和布尔值识别为不同类型,但vb.net希望为可能依赖旧行为的VB6程序提供迁移路径。使用“Option Strict Off”,VB.Net将隐式地将布尔值True转换为整数-1;虽然大多数程序员使用Option Strict On,但CInt()的行为与隐式转换行为不同会让人感到困惑。

答案 6 :(得分:3)

我测试了它并得到了以下结果:

Public Module BooleanTest
Public Function GetTrue() As Boolean
    GetTrue = True
End Function
End Module

...

[StructLayout(LayoutKind.Explicit)]
struct MyStruct
{
    [FieldOffset(0)]
    public bool MyBool;
    [FieldOffset(0)]
    public int MyInt32;
}

static void Main(string[] args)
{
    MyStruct b1, b2;
    b1.MyInt32 = 0;
    b2.MyInt32 = 0;
    b1.MyBool = BooleanTest.BooleanTest.GetTrue();
    b2.MyBool = true;
    Console.WriteLine(b1.MyInt32);
    Console.WriteLine(b2.MyInt32);
}

这将导致:

  

1
  1

我希望这证明.NET中的所有True值始终相同。原因很简单:所有.NET成员都必须相互沟通。如果object.Equals(trueFromCSharp, trueFromVB)会导致错误(trueFromCSharp == trueFromVB),那会很奇怪。

CInt只是一个将True转换为-1的函数。另一个函数Int将返回1。但这些是转换器,并没有说二进制值。

答案 7 :(得分:2)

我遇到了与MySQL相同的问题,因为它没有布尔类型只有一个tinyint(1)。

我的解决方案是编写转换器函数,以确保在将值插入数据库之前值正确

        Public Function BoolToMySql(bVal As Boolean) As Integer
            Dim retVal As Integer
            If bVal = True Then
                retVal = 1
            Else
                retVal = 0
            End If
                 BoolToMySql = retVal
        End Function

答案 8 :(得分:1)

我希望能帮助其他人在VB.NET中与布尔人合作。 正如编写Roger写的VB.NET的更好方法:

Public Function BoolToMySql(bVal As Boolean) As Integer
   return  If(bVal, 1, 0)
End Function