Validation des données
Pourquoi valider les entrées ?
Les données saisies par l'utilisateur ne doivent jamais être considérées comme valides automatiquement. L'utilisateur peut entrer une valeur vide, du texte à la place d'un nombre ou une valeur qui ne respecte pas les règles du programme.
Console.ReadLine() lit une ligne au clavier et retourne toujours une chaîne de caractères (string). Il faut donc vérifier et convertir cette entrée avant de l'utiliser.
Une validation permet de :
- éviter que le programme plante;
- s'assurer que la donnée a le bon type;
- s'assurer que la donnée respecte les règles du programme;
- demander une nouvelle valeur avec un message compréhensible.
Valider un entier avec int.TryParse
int.TryParse tente de convertir une chaîne en nombre entier. La méthode retourne true si la conversion réussit et false dans le cas contraire.
Console.Write("Entrez votre âge : ");
string saisie = Console.ReadLine();
int age;
if (int.TryParse(saisie, out age))
{
Console.WriteLine("Votre âge est " + age + ".");
}
else
{
Console.WriteLine("Veuillez entrer un nombre entier.");
}
La valeur convertie est placée dans la variable age. Si la conversion échoue, le bloc else est exécuté.
Valider un nombre réel avec double.TryParse
Pour une valeur pouvant contenir des décimales, on utilise double.TryParse.
Console.Write("Entrez le prix : ");
string saisie = Console.ReadLine();
double prix;
if (double.TryParse(saisie, out prix))
{
Console.WriteLine("Le prix est de " + prix + " $");
}
else
{
Console.WriteLine("Veuillez entrer un nombre réel.");
}
La conversion vérifie le type de la donnée, mais pas nécessairement sa valeur. Il faut donc ajouter une condition si le programme impose une règle :
double prix;
if (double.TryParse(saisie, out prix))
{
if (prix >= 0)
{
Console.WriteLine("Prix accepté.");
}
else
{
Console.WriteLine("Le prix ne peut pas être négatif.");
}
}
else
{
Console.WriteLine("Veuillez entrer un nombre réel.");
}
Valider une chaîne avec if, else if et else
Une chaîne est déjà retournée par Console.ReadLine(), mais elle peut être vide ou ne pas correspondre aux choix attendus.
Console.Write("Choisissez une couleur (rouge, vert ou bleu) : ");
string couleur = Console.ReadLine();
if (couleur == "rouge")
{
Console.WriteLine("Vous avez choisi le rouge.");
}
else if (couleur == "vert")
{
Console.WriteLine("Vous avez choisi le vert.");
}
else if (couleur == "bleu")
{
Console.WriteLine("Vous avez choisi le bleu.");
}
else
{
Console.WriteLine("Cette couleur n'est pas valide.");
}
On peut aussi vérifier qu'une chaîne n'est pas vide :
Console.Write("Entrez votre prénom : ");
string prenom = Console.ReadLine();
if (string.IsNullOrWhiteSpace(prenom))
{
Console.WriteLine("Le prénom ne peut pas être vide.");
}
else
{
Console.WriteLine("Bonjour " + prenom + " !");
}
string.IsNullOrWhiteSpace retourne true si la chaîne est null, vide ou composée uniquement d'espaces.
Redemander une donnée invalide
Pour obliger l'utilisateur à fournir une donnée valide, on place la lecture dans une boucle while :
int age;
do
{
Console.Write("Entrez votre âge : ");
}
while (!int.TryParse(Console.ReadLine(), out age) || age < 0);
Console.WriteLine("Âge accepté : " + age);
La boucle recommence tant que la saisie n'est pas un entier ou que l'âge est négatif.
Fail fast et sortie anticipée
Fail fast : échouer rapidement
Fail fast signifie échouer rapidement. On vérifie une donnée dès qu'elle est reçue. Si elle est invalide, on arrête immédiatement le traitement au lieu de continuer avec une valeur incorrecte.
Cette approche rend l'erreur plus facile à repérer et évite qu'elle provoque un problème plus loin dans le programme.
int quantite;
if (!int.TryParse(Console.ReadLine(), out quantite))
{
Console.WriteLine("La quantité doit être un entier.");
return;
}
Console.WriteLine("Quantité acceptée : " + quantite);
Early exit : sortie anticipée
Early exit signifie sortie anticipée. C'est le fait de quitter une méthode ou le programme dès que la suite du traitement n'a plus de raison d'être.
Les sorties anticipées évitent d'imbriquer inutilement des blocs if/else et améliorent la lisibilité du code. Les cas invalides sont traités immédiatement, puis le traitement principal reste au même niveau d'indentation.
Console.Write("Entrez un prix positif : ");
string saisie = Console.ReadLine();
double prix;
if (!double.TryParse(saisie, out prix))
{
Console.WriteLine("Prix invalide.");
return;
}
if (prix < 0)
{
Console.WriteLine("Le prix ne peut pas être négatif.");
return;
}
Console.WriteLine("Prix accepté : " + prix + " $");
Ici, les cas invalides sont traités en premier. return quitte immédiatement le programme top-level, sans ajouter de bloc else. Le traitement principal reste visible à la fin du code. On peut traduire early exit par sortie anticipée, retour anticipé ou arrêt anticipé, selon le contexte.
Contre-exemple : sans sortie anticipée
Sans sortie anticipée, on doit imbriquer les blocs if/else. Le code fonctionne, mais il devient plus difficile à lire lorsque le nombre de validations augmente.
// Exemple sans sortie anticipée: À NE PAS SUIVRE
Console.Write("Entrez un prix positif : ");
string saisie = Console.ReadLine();
double prix;
if (double.TryParse(saisie, out prix))
{
if (prix >= 0)
{
Console.WriteLine("Prix accepté : " + prix + " $");
}
else
{
Console.WriteLine("Le prix ne peut pas être négatif.");
}
}
else
{
Console.WriteLine("Prix invalide.");
}