将布尔值转换为整数在VB.NET中
在VB.NET中将布尔值转换为整数的问题的出现是由于遗留代码的影响。
问题的核心在于VT_BOOL类型。Visual Basic 6.0使用VT_BOOL类型(也称为VARIANT_BOOL)来表示布尔值。在VT_BOOL中,True被表示为值VARIANT_TRUE,其整数值为-1。在转换到.NET时,决定使用Visual Basic的转换例程将布尔值转换为整数值,并保持Visual Basic 6.0的语义,即返回值为-1。
首次发生的隐式转换出现在 b = i 这一行。在底层,这会将整数隐式转换为布尔值。任何非零值都被视为true,因此结果值为true。
然而,下一行代码进行了对整数类型的隐式转换。
i = b
在底层,这使用了Visual Basic的转换例程(CType或CInt)将值转换为整数。因此,采用了Visual Basic的语义,返回的值为-1。
下一个有趣的行是Convert.ToInt32()
这一行。这使用了一个不使用Visual Basic语义的.NET转换例程。相反,它返回真布尔值的底层BCL表示,即1。
也许你想了解一下为什么要使用VT_BOOL以及为什么它的值是-1。VB 6只有1组“and”和“or”运算符,既可以进行逻辑运算也可以进行位运算(大多数语言有2组运算符)。这是通过将“and”实现为“&”并将字面值默认为-1来实现的。
这样,“true and x”在“x”为非零时都是非零的。
您可以在这里找到我回答一个与此大部分无关的问题的答案,了解更多关于为什么使用VT_BOOL的原因:https://stackoverflow.com/a/46331671/3043
那么这如何解释编译器为什么对将布尔值转换为整数时会执行-(b > false)
?
在某些编程语言中,布尔值的true被认为是-1而不是1。在VB6中,常量True的值是-1。然而,Convert.ToInt32(Boolean)被文档化为返回“如果值为true,则返回数字1;否则返回0。”这样,无论使用哪种框架语言,结果都是相同的。
一些语言使用-1作为True,因为它的二进制表示是0b11111111,每一位都是0的二进制表示的反码,因此对一个进行位NOT操作会得到另一个。
在.NET 4.0中,CInt(true)的结果是-1,而Convert.ToInt32(true)的结果是1。
解决方法见下一个问题:boolean true -- positive 1 or negative 1。