Lancer un booléen à un entier renvoie -1 pour true?

Je travaille avec du code VB.NET qui semble CInt(myBoolean) une valeur booléenne en un entier en utilisant CInt(myBoolean) . La chose étrange qui se passe est qu’elle retourne -1 si la valeur est vraie. Par exemple:

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

Est-ce courant dans d’autres langues?

Je pensais qu’un booléen serait 1 si vrai et 0 si faux. En outre, existe-t-il un moyen de faire en sorte que Visual Basic atsortingbue 1 à true au lieu d’atsortingbuer -1?

En règle générale, la valeur false est représentée par 0 et la valeur true est représentée par une valeur entière différente de 0. La valeur spécifique pour true et false (entre autres) est des choses sur lesquelles vous ne devriez pas compter – elles peuvent potentiellement être spécifiques à l’implémentation. Je ne suis pas sûr de ce que vous essayez de faire, mais il serait probablement préférable de ne pas utiliser True ou False avec des valeurs entières spécifiques, sauf si vous devez absolument le faire.

La meilleure explication que je pourrais trouver pour le comportement spécifique de VB provient de Wikipedia :

Constante booléenne True a une valeur numérique −1. Cela est dû au fait que le type de données booléen est stocké sous la forme d’un entier signé 16 bits. Dans cette construction, -1 est évalué à 16 1 binarys (la valeur booléenne True) et 0 à 16 0 (la valeur booléenne False). Ceci est apparent lors de l’exécution d’une opération Not sur une valeur entière signée de 16 bits 0 qui renverra la valeur entière -1, c’est-à-dire True = Non Faux. Cette fonctionnalité inhérente devient particulièrement utile lors de l’exécution d’opérations logiques sur les bits individuels d’un entier tel que And, Or, Xor et Not. [4] Cette définition de True est également compatible avec BASIC depuis la mise en œuvre de Microsoft BASIC au début des années 1970 et est également liée aux caractéristiques des instructions de processeur à ce moment-là.

Un travail autour de votre utilisation initiale serait:

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

Cela retournera un 0.

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

Cela retournera un 1.

Cela ressemble à un piège et je ne connais aucun autre exemple de ce comportement.

http://msdn.microsoft.com/en-us/library/ae382yt8.aspx spécifie ce comportement, avec une remarque “Don’t do that, mkay”. Noter plus bas:

Conversion dans le cadre

La méthode ToInt32 de la classe Convert dans l’espace de noms System convertit True en +1.

Si vous devez convertir une valeur booléenne en un type de données numérique, faites attention à la méthode de conversion utilisée.

La documentation MSDN fournit des informations précieuses:

Les valeurs booléennes ne sont pas stockées sous forme de nombres et les valeurs stockées ne sont pas censées être équivalentes à des nombres. Vous ne devez jamais écrire de code reposant sur des valeurs numériques équivalentes pour True et False. Dans la mesure du possible, vous devez restreindre l’utilisation des variables booléennes aux valeurs logiques pour lesquelles elles ont été conçues.

J’ai eu le même problème et Math.Abs utilisé la fonction Math.Abs sur le résultat 🙂

Dans les années 1970 et 1980, de nombreuses versions de BASIC implémentaient une arithmétique bit par bit avec leurs opérateurs AND et OR , et les expressions conditionnelles vraies étaient évaluées à -1 (ce qui correspondait à la valeur «ensemble de tous les bits»). Je ne suis pas sûr de savoir exactement pourquoi la décision a été prise d’évaluer de véritables expressions conditionnelles à une valeur de tous les bits; être capable d’utiliser AND pour masquer un entier contre une expression conditionnelle peut avoir été plus rapide que multiplier, mais compte tenu de la mécanique interne des interprètes, la différence aurait été légère.

Dans tous les cas, les premières versions de BASIC produites par Microsoft pour le PC suivaient cette tradition d’avoir des conditions réelles évaluées à -1 (ensemble de tous les bits); QuickBASIC étant à son tour supposé être compatible avec ceux-ci, et Visual Basic étant supposé être compatible avec QuickBASIC, ils utilisaient la même représentation. Bien que .Net reconnaisse les entiers et les booléens comme des types différents, vb.net souhaitait proposer un chemin de migration pour les programmes VB6 pouvant s’appuyer sur l’ancien comportement. Avec “Option Ssortingct Off”, VB.Net convertira implicitement une valeur booléenne de True en un entier -1; CInt() que la plupart des programmeurs utilisent Option Ssortingct On , il est déroutant que le comportement de CInt() diffère du comportement de conversion implicite.

Je l’ai testé et j’ai obtenu les résultats suivants:

 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(ssortingng[] 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); } 

Cela se traduira par:

1
1

J’espère que cela prouve que toutes les valeurs True dans .NET sont toujours les mêmes. La raison est simple: tous les membres .NET doivent communiquer entre eux. Ce serait bizarre si object.Equals(trueFromCSharp, trueFromVB) aurait comme résultat false (comme le serait trueFromCSharp == trueFromVB ).

CInt est juste une fonction qui convertira True en -1 . Une autre fonction Int retournera 1 . Mais ce sont des convertisseurs et ne disent rien sur les valeurs binarys.

J’ai eu le même problème avec MySQL car il n’a pas de type booléen seulement un tinyint (1).

Ma solution consistait à écrire une fonction de convertisseur pour vérifier que les valeurs sont correctes avant de les insérer dans la firebase database.

  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 

J’espère que cela peut aider les autres à travailler avec Booleans dans VB.NET. Juste comme un meilleur moyen d’écrire le VB.NET que Roger a écrit:

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