C# ne convertit jamais de lui-même entre des types sans rapport. Une chaîne qui contient des chiffres reste une chaîne, et un double ne devient pas discrètement un int. Vous convertissez explicitement, et l'outil à utiliser dépend de ce que vous convertissez : du texte en nombre (analyse ou parsing), un type numérique en un autre (cast), ou un objet en un type plus précis (as, is).
String en int : Parse, TryParse et Convert
Il existe trois façons standard de transformer du texte en int :
Sortie :
2500
TryParse ok: 1250
TryParse failed, d = 0
42
-17
int.TryParse renvoie un bool et écrit le résultat dans une variable out, qui vaut 0 en cas d'échec. Comme une saisie invalide est normale pour tout ce que tape un utilisateur, TryParse est le choix par défaut pour les saisies, les fichiers et les query strings. Les mêmes méthodes existent sur chaque type numérique : long.TryParse, double.TryParse, decimal.Parse, etc.
Ce que fait chacune avec une saisie invalide
Les trois méthodes ne diffèrent que par leur manière d'échouer :
Sortie :
int.Parse(null) throws ArgumentNullException
Convert.ToInt32(null) = 0
int.Parse("abc") throws FormatException
int.Parse("12.5") throws FormatException
int.Parse("1,000") throws FormatException
int.Parse("9999999999") throws OverflowException
int.Parse("") throws FormatException
Une FormatException porte le message bien connu « Input string was not in a correct format » (depuis .NET 8, « The input string '12.5' was not in a correct format », avec le texte cité), et c'est l'une des erreurs d'exécution C# les plus courantes : "12.5" n'est pas un int, pas plus que "1,000". Pour les accepter, analysez-les comme decimal, ou indiquez à l'analyseur quels styles sont autorisés :
Sortie :
1000
255
13
10
La culture : pourquoi "1.5" peut devenir 15
L'analyse utilise par défaut la culture courante, et les cultures ne s'accordent pas sur les séparateurs. En allemand et dans plusieurs autres cultures européennes, le séparateur décimal est une virgule et le point groupe les milliers. La même chaîne donne des nombres différents :
Sortie :
1.5
15
1.5
Le code qui lit des fichiers de données, du JSON, de la configuration ou tout contenu généré par une machine doit toujours passer CultureInfo.InvariantCulture, à l'analyse comme au formatage. Sinon, le même programme fonctionne sur la machine d'un développeur et lit mal chaque nombre sur un serveur réglé dans une autre langue. N'utilisez la culture courante que pour le texte qu'une personne a tapé ou lira.
Conversions numériques implicites et explicites
Les conversions élargissantes se font implicitement : int vers long, int vers double, float vers double, int vers decimal. Une conversion qui peut perdre l'ordre de grandeur de la valeur ou sa partie fractionnaire exige un cast explicite (type)value. Une exception à retenir : int ou long vers float, et long vers double, sont implicites alors qu'elles peuvent perdre de la précision : float f = 16_777_217; compile et stocke 16777216.
Sortie :
9 -9
10
2
4
705032704
9.99
7 7.0 7
Trois choses à retenir. Un cast d'un nombre à virgule flottante vers un entier tronque ; il n'arrondit pas. Convert.ToInt32(double) arrondit, avec l'arrondi bancaire (les demis vont vers le voisin pair). Et un cast entier qui ne tient pas boucle silencieusement, sauf dans un contexte checked, où il lève OverflowException (voir types de données).
int x = 3.7; est une erreur de compilation (CS0266: cannot implicitly convert type 'double' to 'int', an explicit conversion exists) : le compilateur vous demande de choisir entre un cast et une méthode d'arrondi.
Nombres et autres types vers string
Chaque type a ToString(), et les types numériques acceptent une chaîne de format. L'interpolation de chaînes appelle le même formatage :
Sortie :
42
000042
1234.50
1,234.50
$1,234.50
FF
1010
True
Order 000042: 1234.50
Les codes de format (D, F, N, C, X, P, E) et les modèles personnalisés comme "0.00" sont traités dans interpolation de chaînes.
Caractères et booléens
Sortie :
7
55
7
7
A
True
False
1
False
(int)'7' vaut 55, le code du caractère, pas 7. Cela piège quiconque additionne les chiffres d'un nombre ; soustrayez '0' ou utilisez char.GetNumericValue. bool.Parse accepte "true" et "false" quelle que soit la casse, et rien d'autre ("yes" et "1" lèvent une exception).
Conversions de références : casts, as et is
Pour les types classe, un cast vérifie le type réel de l'objet à l'exécution. La conversion vers une classe de base (upcast) est implicite. La conversion vers une classe dérivée (downcast) exige un cast explicite, qui lève InvalidCastException quand l'objet est d'un autre type :
Sortie :
4242
True
Card ending 4242, 50.00
InvalidCastException
5
cannot unbox int as long
Préférez is avec une variable quand vous devez choisir une branche selon le type : c'est un seul test, il ne peut pas lever d'exception, et la nouvelle variable n'est visible que là où le test a réussi. Utilisez un cast simple quand un autre type serait un bug qui doit échouer bruyamment. Le cas de l'int boxé piège ceux qui lisent des nombres depuis des collections d'object ou des cellules de DataRow : faites d'abord l'unboxing vers le type exact ((long)(int)boxed), ou utilisez Convert.ToInt64(boxed), qui gère n'importe quel type numérique.
Questions fréquentes
Comment convertir une string en int en C# ?
Utilisez int.TryParse(text, out int number) quand le texte vient d'un utilisateur, d'un fichier ou du réseau : la méthode renvoie false au lieu de lever une exception quand le texte n'est pas un nombre valide. Utilisez int.Parse(text) quand un texte invalide est un bug et qu'une exception est la bonne réponse. Convert.ToInt32(text) se comporte comme int.Parse, sauf qu'il renvoie 0 pour null.
Quelle est la différence entre int.Parse et Convert.ToInt32 ?
Pour les chaînes, ils sont presque identiques : tous deux lèvent FormatException sur un texte comme "abc" et OverflowException sur un nombre hors plage. La différence est null : int.Parse(null) lève ArgumentNullException, alors que Convert.ToInt32(null) renvoie 0. Convert.ToInt32 accepte aussi d'autres types (double, bool, object) et arrondit un double à l'entier pair le plus proche au lieu de le tronquer.
Que signifie « Input string was not in a correct format » ?
C'est le message d'une FormatException levée par int.Parse, double.Parse ou Convert.ToInt32 (depuis .NET 8, il devient « The input string 'abc' was not in a correct format » et cite le texte) quand le texte n'est pas un nombre au format attendu : des lettres, une chaîne vide, un point décimal alors qu'on analyse un int, ou un séparateur de milliers. Passez à TryParse pour gérer une mauvaise saisie sans exception, et vérifiez dans quelle culture le nombre a été écrit.
Comment convertir un double en int en C# ?
Écrivez un cast explicite : int n = (int)price;. Le cast tronque vers zéro, donc (int)9.99 vaut 9 et (int)-9.99 vaut -9. Pour arrondir, utilisez (int)Math.Round(price), en notant que Math.Round arrondit par défaut les demis au nombre pair le plus proche ; passez MidpointRounding.AwayFromZero pour l'arrondi scolaire.
Quelle est la différence entre as et un cast en C# ?
Un cast (Dog)animal lève InvalidCastException si l'objet n'est pas un Dog. animal as Dog renvoie null à la place, il doit donc être suivi d'un test de nullité, et il ne fonctionne qu'avec les types référence et nullables. L'alternative moderne est le pattern is : if (animal is Dog dog) { ... } teste et convertit en une seule étape.