Dépannage des types de données (Visual Basic)
Cette page répertorie des problèmes courants qui peuvent se produire lorsque vous exécutez des opérations sur des types de données intrinsèques.
Les expressions à virgule flottante ne sont pas considérées comme égales
Lorsque vous utilisez des nombres à virgule flottante (Single, type de données (Visual Basic) et Double, type de données (Visual Basic)), n'oubliez pas qu'ils sont stockés sous forme de fractions binaires. En d'autres termes, ils ne peuvent pas contenir une représentation exacte d'une quantité qui n'est pas une fraction binaire (sous la forme k / (2 ^ n) où k et n désignent des entiers). Par exemple, 0,5 (= 1/2) et 0,3125 (= 5/16) peuvent être considérés comme des valeurs précises, tandis que 0,2 (= 1/5) et 0,3 (= 3/10) peuvent être uniquement des approximations.
En raison de cette imprécision, vous ne pouvez pas vous baser sur des résultats exacts lorsque vous utilisez des valeurs à virgule flottante. En particulier, deux valeurs qui sont théoriquement égales peuvent présenter des représentations légèrement différentes.
Pour comparer des quantités à virgule flottante |
|
L'exemple suivant présente une comparaison correcte et incorrecte de deux valeurs Double.
Dim oneThird As Double = 1.0 / 3.0
Dim pointThrees As Double = 0.333333333333333
' The following comparison does not indicate equality.
Dim exactlyEqual As Boolean = (oneThird = pointThrees)
' The following comparison indicates equality.
Dim closeEnough As Double = 0.000000000000001
Dim absoluteDifference As Double = Math.Abs(oneThird - pointThrees)
Dim practicallyEqual As Boolean = (absoluteDifference < closeEnough)
MsgBox("1.0 / 3.0 is represented as " & oneThird.ToString("G17") &
vbCrLf & "0.333333333333333 is represented as " &
pointThrees.ToString("G17") &
vbCrLf & "Exact comparison generates " & CStr(exactlyEqual) &
vbCrLf & "Acceptable difference comparison generates " &
CStr(practicallyEqual))
L'exemple précédent utilise la méthode ToString de la structure Double pour spécifier une plus grande précision que le mot clé CStr. La valeur par défaut est 15 chiffres, mais le format « G17 » l'étend à 17 chiffres.
L'opérateur Mod ne retourne pas de résultat précis
En raison de l'imprécision du stockage à virgule flottante, Mod, opérateur (Visual Basic) peut retourner un résultat inattendu lorsqu'au moins un des opérandes est à virgule flottante.
Decimal, type de données (Visual Basic) n'utilise pas la représentation à virgule flottante. Plusieurs nombres qui sont inexacts dans Single et Double sont exacts dans Decimal (par exemple, 0,2 et 0,3). Bien que l'arithmétique soit plus lente en Decimal qu'en virgule flottante, cela peut valoir la peine de réduire les performances pour obtenir une plus grande précision.
Pour rechercher le reste entier de quantités à virgule flottante |
|
L'exemple suivant montre l'imprécision potentielle des opérandes à virgule flottante.
Dim two As Double = 2.0
Dim zeroPointTwo As Double = 0.2
Dim quotient As Double = two / zeroPointTwo
Dim doubleRemainder As Double = two Mod zeroPointTwo
MsgBox("2.0 is represented as " & two.ToString("G17") &
vbCrLf & "0.2 is represented as " & zeroPointTwo.ToString("G17") &
vbCrLf & "2.0 / 0.2 generates " & quotient.ToString("G17") &
vbCrLf & "2.0 Mod 0.2 generates " &
doubleRemainder.ToString("G17"))
Dim decimalRemainder As Decimal = 2D Mod 0.2D
MsgBox("2.0D Mod 0.2D generates " & CStr(decimalRemainder))
L'exemple précédent utilise la méthode ToString de la structure Double pour spécifier une plus grande précision que le mot clé CStr. La valeur par défaut est 15 chiffres, mais le format « G17 » l'étend à 17 chiffres.
Étant donné que zeroPointTwo a la valeur Double, sa valeur pour 0,2 est une fraction binaire se répétant à l'infini avec une valeur stockée de 0,20000000000000001. Lorsqu'on divise 2,0 par cette quantité, on obtient 9,9999999999999995 avec un reste de 0,19999999999999991.
Dans l'expression pour decimalRemainder, le caractère de type de littéral D force les deux opérandes sur la valeur Decimal et 0,2 a une représentation précise. Par conséquent, l'opérateur Mod obtient le reste attendu de 0,0.
Notez que cela n'est pas suffisant pour déclarer decimalRemainder comme Decimal. Vous devez également forcer les littéraux sur la valeur Decimal, ou ils utilisent la valeur par défaut Double et decimalRemainder reçoit la même valeur inexacte que doubleRemainder.
Impossible de convertir correctement le type Boolean en type numérique
Les valeurs Booléen, type de données (Visual Basic) ne sont pas stockées en tant que nombres et les valeurs stockées ne sont pas destinées à être équivalentes aux nombres. Pour garantir la compatibilité avec les versions antérieures, Visual Basic fournit des mots clés de conversion (Fonction CType (Visual Basic), CBool, CInt, etc.) pour effectuer des conversions entre des types Boolean et numériques. Toutefois, d'autres langages exécutent parfois différemment ces conversions, comme c'est le cas pour les méthodes du .NET Framework.
Vous ne devez jamais écrire un code qui repose sur les valeurs numériques équivalentes à True et False. Autant que possible, limitez l'utilisation des variables Boolean aux valeurs logiques pour lesquelles elles sont conçues. Si vous devez combiner Boolean et des valeurs numériques, assurez-vous que vous comprenez la méthode de conversion que vous sélectionnez.
Conversion dans Visual Basic
Lorsque vous utilisez les mots clés de conversion CType ou CBool pour convertir des types de données numériques en Boolean, 0 devient False et toutes les autres valeurs deviennent True. Lorsque vous convertissez des valeurs Boolean en types numériques à l'aide de mots clés de conversion, False devient 0 et True devient -1.
Conversion dans la structure
La méthode ToInt32 de la classe Convert dans l'espace de noms System convertit True en +1.
Si vous devez convertir une valeur Boolean en un type de données numériques, choisissez attentivement la méthode de conversion à utiliser.
Un littéral de caractère génère une erreur du compilateur
En l'absence de caractères de type, Visual Basic utilise des types de données par défaut pour les littéraux. Le type par défaut pour un littéral de caractère — mis entre guillemets (" ") — est String.
Le type de données String ne s'étend pas au Char, type de données (Visual Basic). Cela signifie que si vous souhaitez assigner un littéral à une variable Char, vous devez soit effectuer une conversion restrictive soit forcer le littéral sur le type Char.
Pour créer un littéral de caractère à assigner à une variable ou une constante |
|
L'exemple suivant présente des assignations infructueuses et réussies d'un littéral sur une variable Char.
Dim charVar As Char
' The following statement attempts to convert a String literal to Char.
' Because Option Strict is On, it generates a compiler error.
charVar = "Z"
' The following statement succeeds because it specifies a Char literal.
charVar = "Z"c
' The following statement succeeds because it converts String to Char.
charVar = CChar("Z")
Il existe toujours un risque lié à l'utilisation de conversions restrictives, car elles peuvent échouer au moment de l'exécution. Par exemple, une conversion de String en Char peut échouer si la valeur String contient plusieurs caractères. Par conséquent, l'utilisation du caractère de type C est préconisée.
Échec de la conversion de chaîne au moment de l'exécution
Le type de données String (String, type de données (Visual Basic)) participe à très peu de conversions étendues. String s'étend uniquement à lui-même et à Object, et seuls Char et Char() (tableau Char) s'étendent à String. Cela s'explique par le fait que les variables et les constantes String peuvent contenir des valeurs qui ne sont pas prises en charge par d'autres types de données.
Lorsque le commutateur de vérification de type (Option Strict, instruction) a la valeur on On, le compilateur rejette toutes les conversions restrictives implicites. Y compris celles qui impliquent String. Votre code peut toujours utiliser les mots clés de conversion tels que CStr et Fonction CType (Visual Basic), qui invitent le .NET Framework à tenter la conversion.
Notes
L'erreur de conversion restrictive est supprimée pour les conversions à partir des éléments d'une collection For Each…Next vers la variable de contrôle de boucle.Pour plus d'informations et d'exemples, consultez la section « Conversions restrictives » dans For Each...Next, instruction (Visual Basic).
Protection de la conversion restrictive
L'inconvénient des conversions restrictives est qu'elles peuvent échouer au moment de l'exécution. Par exemple, si une variable String contient une valeur autre que « True » ou « False », elle ne peut pas être convertie en Boolean. Si elle contient des caractères de ponctuation, la conversion en un type numérique échoue. Vous ne devez pas tenter de conversion sauf si vous savez que votre variable String contient toujours des valeurs que le type de destination peut accepter.
Si vous devez effectuer une conversion de String en un autre type de données, la procédure la plus sûre consiste à insérer la conversion tentée dans Try...Catch...Finally, instruction (Visual Basic). Cela vous permet de gérer les défaillances au moment de l'exécution.
Tableaux de caractères
Un élément Char unique et un tableau d'éléments Char s'étendent tous deux à String. Toutefois, String ne s'étend pas à Char(). Pour convertir une valeur String en un tableau Char, vous pouvez utiliser la méthode ToCharArray de la classe String.
Valeurs sans signification
En général, les valeurs String ne sont pas explicites dans d'autres types de données, et la conversion est très artificielle et dangereuse. Autant que possible, limitez l'utilisation des variables String aux séquences de caractère pour lesquelles elles sont conçues. Vous ne devez jamais écrire un code qui dépend de valeurs équivalentes dans d'autres types.
Voir aussi
Référence
Liste des types de données (Visual Basic)
Fonctions de conversion de types de données (Visual Basic)
Concepts
Types de données en Visual Basic
Caractères de type (Visual Basic)
Types valeur et types référence
Utilisation efficace des types de données (Visual Basic)