Cours VB.NETDate de mise à jour : 05/12/2010
V-X. Les génériques
V-X-1. Définition
V-X-2. Intérêts des génériques ?
V-X-3. Usage des génériques
V-Y. Linq
V-Y-1. Définition, mise en place
V-Y-2. Principe d'une requête Linq
V-Y-3. Link et les tableaux d'Integers
V-Y-4. Link et les chaînes de caractères
V-Y-5. Link et les mots d'une chaîne de caractères
V-Y-6. Link pour rechercher la différence entre deux listes de noms
V-Y-7. Link et les contrôles
V-Y-8. Inference de Type et type anonyme
V-Z. Les 'Region', compilation conditionnelle, 'Attributs'
V-Z-1. Les Régions
V-Z-2. La Compilation conditionnelle
V-Z-3. Les Attributs
V-AA. Traiter les erreurs
V-AA-1. Les erreurs de syntaxe
V-AA-2. Les erreurs d'exécution
V-AA-3. Les erreurs de logique
V-AA-4. Les Tests
V-X. Les génériques
Super complexe? non!!
V-X-1. Définition
A partir de VB 2005 on peut utiliser les génériques.
Un type générique (Generic) permet de créer une Classe ou une procédure, ayant des Data Types non définis au départ.
En d'autres termes, les paramètres et variables n'ont pas de type: ce ne sont pas des Strings, des Integers.. Ce sont des génériques. Quand on utilise la Classe ou la procédure, on indique le type.
Les génériques nous permettent de définir un comportement ou un algorithme commun sur les types ou un sous ensemble de types .Net. Ils sont un moyen de mutualiser un comportement.
Par exemple, je vais écrire une routine de calcul avec des génériques, elle sera utilisable avec des Integers, des Singles..
Exemple de Fonction utilisant un 'generic'.
Permettant d'en comprendre l'intérêt:
Créons une sub nommée Swap ( elle sert à intervertir 2 variables) fonctionnant pour tous les types de données:
Private Sub Swap (Of ItemType) (ByRef v1 As ItemType, ByRef v2 As ItemType)
Dim temp As ItemType
temp = v1
v1 = v2
v2 = temp
End Sub
|
Notons que en plus des 2 paramètres v1 et v2 à 'swapper' ,"Of ItemType" indique le type de donnée qui doit être utilisé.
Si on a 2 entiers à swapper, il faut appeler la fonction Swap comme cela:
Si ce sont des Strings:
Le JIT compile la fonction Swap comme si elle avait été écrite pour des Strings.
Sans les génériques j'aurais fait plusieurs routines de code pour chaque Type. Or en utilisant les génériques cette redondance peut être évitée.
Exemple de Classe utilisant un 'generic'. A revoir quand vous connaîtrez les classes.
De la même manière, on peut créer une Classe entièrement générique:
Public Class SomeClass (Of ItemType)
Private internalVar as ItemType
Public Function SomeMethod (ByVal value As ItemType) As ItemType
. . .
End Function
End Class
|
Exemple de Collection utilisant un 'generic'.
On peut créer une collection générique (System.Collections.Generic) et lui imposer un type.
Exemple: créons une collection de String : List(Of String).
Imports System. Collections . Generic .
Dim l As New List (Of String )
l. Add (" toto " )
Dim S As String = l. Item (0)
|
Habituellement les collections contiennent des objets; ici c'est une collection de String.
Je ne peux y mettre que des String (sinon cela provoque une erreur).
Comme par définition c'est des string, il n'y a pas de conversion String=>Objet et Objet=>String (pas de boxing/unboxing)
On peut aussi créer des Stack(Of..) Queue(Of..), Dictionnary(Of..) SortedList(Of..)..
V-X-2. Intérêts des génériques ?
Pourquoi ne pas utiliser des types 'Object' à la place des génériques?
Les génériques sont fortement typés. Si on crée une collection générique de Long, on ne peut utiliser que des Long: c'est mieux, cela évite les erreurs, les conversions de type.
Ils sont plus rapides que l'usage des objets.
S'il y a erreur, elle se produit probablement à la compilation et pas à l'exécution.
Cela permet d'utiliser l'intellisense.
Comparaison ArrayList (non générique) et List (Of) générique.
Si on utilise une ArrayList qui est une liste non générique, on peut sans problèmes ajouter un Integer puis une String: cela n'est pas logique et possiblement une erreur.
De plus quand on travaille sur cette liste ou qu'on parcourt cette liste il y a des opérations de Cast et de boxing/unboxing sans arrèts: on stocke des Integer, String dans des objets.
Par contre si on utilise une List générique typée, pas de Cast ni de boxing (rapidité++) et reduction du nombre d'erreur possible: une List de String ne peut contenir que des String.
V-X-3. Usage des génériques
On peut utiliser des méthodes génériques pour travailler sur les tableaux.
Exemple recherche dans un tableau de short nommé monTab l'élément 2
index= Array . indexOf (Of Short)(monTab, 2)
|
est hyper plus rapide que
index= Array.indexOf (monTab, 2) car la première version avec généric est directement optimisée pour les Short.
Il est de même pour Binarysearch et Sort.
Cela est valable pour les types 'valeur' (peu d'intérêts pour les strings par exemple).
Collections génériques:
On peut créer une collection générique (System.Collections.Generic) et lui imposer un type.
Exemple: créons une collection de String (List(Of String)): Elle est typée car elle ne peut contenir que des 'String'.
Dim l As New List (Of String )
Il s
l. Add (" toto " )
Dim S As String = l. Item (0)
|
Il y a aussi de nouveaux types de collections génériques
-Les Dictionnary(Of..) avec Clé et valeur
-Les SortedDictionnary(Of..) avec Clé et valeur trié.
-Les LinkedList(Of..) Liste Chaînée, chaque élément comportant une propriété Value, Next et Previous.
-Les SortedList(Of..)..
-Les Stack(Of..)
-Les Queue(Of..)
On peut aussi créer des collections 'composées'.
Dim genericColl As New Dictionary (Of String , String )
genericColl. Add (" PremiereClé " , item1)
|
V-Y. Linq
'Language-Integrated Query' (LINQ), veut dire "langage de requête intégré".
On l'utilise dans VB à partir de VB2008 (Framework 3.5).
V-Y-1. Définition, mise en place
C'est un langage de requêtes (permettant d'interroger une source de données) directement dans le code Visual Basic et à l'aide de mots clés familiers (issues du SQL, le langage d'interrogation des bases de données).
Cette source de données peut être une Base de données (Linq To SQL et Linq To DataSet )un fichier XML (Link To XML) mais aussi une collection, un tableau, une chaîne de caractères.
On parle dans ce dernier cas de 'Linq To Objects'. Si un objet prend en charge l'interface IEnumerable ou IEnumerable (Of), le fournisseur LINQ to Objects vous permet de l'interroger.
LINQ (dixit Microsoft) offrent trois principaux avantages par rapport aux boucles for Each traditionnelles :
Les requêtes:
-Elles sont plus concises et lisibles, surtout lors du filtrage de plusieurs conditions.
-Elles fournissent des fonctions puissantes de filtrage, de classement et de regroupement avec un minimum de code d'application.
-Elles peuvent être appliquées à d'autres sources de données avec peu ou pas de changement.
Pour que LINQ soit pris en compte il faut:
Utiliser VB 2008 et le framework 3.5.
Dans les propriétés, onglet compile, il faut que Option Infer=On
Il faut ajouter System.Data.Linq:
Si vous créez un nouveau projet dans VB 2008, toutes les conditions sont effectives par défaut, si vous modifiez un ancien projet, il faut rajouter certaines références:
Dans l'Explorateur de solutions (Projet, Propriétés..), cliquez sur Références, puis cliquez sur Ajouter une référence.
Cliquez sur .NET, sur l'assembly System.Data.Linq, puis sur OK, cela ajoute la référence.
Il faut ajouter l'espace de nom:
Dans l'explorateur de solution cocher Systel.Data.Link comme ci-dessus
ou ajouter les directives suivantes en haut du Module1 :Imports System.Data.Linq
V-Y-2. Principe d'une requête Linq
A titre d'exemple simpliste, on a des données dans MyData et chaque donnée a les champs 'Nom', "Prenom", "Ville"... Comment chercher les enregistrements ayant comme nom "toto"?
Dim Resultat = From Element In MyData _
Where Element. Nom = " Toto " _
Select Element
|
On crée une variable de requête (ici ' Dim Resultat') qui sera chargée de contenir la requête (et pas les résultats),
puis l'expression de requête composée de:
From : dans quoi chercher? dans quel élément?
In : quelle source de données? dans MyData.
Where : précise les conditions à appliquer, c'est le 'filtre'.
Select: Précise les éléments à extraire qui vont apparaître dans 'Resultat'
Remarquons que Dim From In Where Select doivent être sur une seule unique et même ligne; pour la lisibilité, on écrit sur plusieurs lignes en ajoutant des continuateurs de lignes " _".
Remarquons aussi qu'initialement on connaît MyData et on sait que chaque élément de MyData a un champ 'Nom', c'est tout!! On utilise dans la requête les nouvelles variables 'Resultat' et 'Element' sans avoir à déclarer leurs types (on aurait pu le faire). 'Element' est une variable de portée déduite comme élément de MyData.
Ce fonctionnement particulier de LINQ est possible grâce à l'inférence de type et aux types anonymes (voir plus bas).
Et pour afficher les noms dans une ListBox:
For Each P In Resultat
ListBox1. Items . Add (P. NOM )
Next
|
Ici la requête contenue dans la variable de requête 'Resultat' est exécutée pour 'alimenter' la boucle 'For Each'.
On remarque donc que l'exécution est différée.
On peut 'forcer' l'exécution immédiate en mettant la requête entre parenthèses et en utilisant une propriété (.Count , .ToArray, .ToList ):
Dim ListPersonneAyantPrenomToto = (From Element In MyData _
Where Element. Nom = " Toto " _
Select Element). ToList ()
Dim NombrePersonneAyantPrenomToto = (From Element In MyData _
Where Element. Nom = " Toto " ). Count ()
|
On peut aussi utiliser .ToList ou .ToArray en mode différé:
Dim Resultat = From Element In MyData _
Where Element. Nom = " Toto " _
Select Element
Dim Tableau = Resultat. ToArray ()
|
Order By permet de trier les résultats.
Dim Resultat = From Element In MyData _
Order By Element. Price Descending, Element. Nom _
Select Element. Nom , Element. Price
|
Ici on trie par prix décroissant, puis à prix égal sur le nom croissant.
Remarquons qu'on sélectionne seulement 2 'colonnes'.
Il est possible d'avoir plusieurs sources, dans ce cas chaque bloc .In est séparé par une virgule:
Dim queryResults = From cust In customers, ord In orders _
Where cust. CustomerID = ord. CustomerID _
Select cust, ord
|
La clause Where peut contenir des conditions complexes avec des AND des OR..
Dim custs = From cust In db. Customers _
Where cust. Country = " France " _
And (cust. CompanyName . StartsWith (" F " ) _
Or cust. CompanyName . StartsWith (" V " )) _
Order By cust. CompanyName _
Select cust. CompanyName , cust. City
DataGridView1. DataSource = custs
|
V-Y-3. Link et les tableaux d'Integers
Un tableau peut être interrogé par Linq.
Exemple: rechercher les nombres pairs dans un tableau d'Integer :
Dim numbers () As Integer = {0, 1, 2, 3, 4, 5, 6}
Dim réponses = From num In numbers _
Where num Mod 2 = 0 _
Select num
For Each number In réponses
Console. Write (number & " " )
Next
|
Cela affiche sur la console(menu Affichage puis Sortie): 0 2 4 6
On peut vouloir compter uniquement les nombres pairs:
Dim nombredepair = (From num In numbers _
Where num Mod 2 = 0 _
Select num). Count ()
Console. Write (nombrepair)
|
On remarque que dans le premier exemple (Select num) l'exécution de la requête est effectuée au cours de la boucle For Each (exécution différée par rapport à la création) alors que dans le second exemple (count) , l'exécution est immédiate.
V-Y-4. Link et les chaînes de caractères
Soit une chaîne de caractères MyString, rechercher les caractères qui sont des nombres.
Dim MyString As String = " ABCjkjhkhs666KMOOP "
Dim Query = From ch In MyString _
Where ch. IsDigit (ch) _
Select ch
For Each c As Char In Query
Console. Write (c & " " )
Next
Dim count As Integer = Query. Count ()
Console. WriteLine (" Count = " & count)
|
On remarque qu'il n'est pas nécessaire de réexecuter la requête.
Autre syntaxe:
Sélectionner tous les caractères avant '6'
Dim Query2 = MyString. TakeWhile (Function (c) c < > " 6 " )
For Each ch In Query2
Console. Write (ch)
Next
|
Ici on a utilisé TakeWhile qui sélectionne les caractères jusqu'à 6. (les sélectionne une seule fois). On a utilisé une expression lambda (voir le chapitre sur les expressions lambdas).
Dim Query2 = MyString. Except (" 6 " )
|
Ici on a utilisé Except qui sélectionne les caractères sauf 6.
V-Y-5. Link et les mots d'une chaîne de caractères
Rechercher combien de fois une String contient le mot 'Basic':
Dim text As String = " Ceci est un cours Visual Basic " & _
" pour les débutants et les autres "
Dim searchTerm As String = " Basic "
Dim dataSource As String () = text. Split (New Char () {" " , " , " , " . " , " ; " , " : " }, _
StringSplitOptions. RemoveEmptyEntries )
Dim Query = From word In dataSource _
Where word. ToLowerInvariant () = searchTerm. ToLowerInvariant () _
Select word
Dim count As Integer = Query. Count ()
Console. WriteLine (count )
|
V-Y-6. Link pour rechercher la différence entre deux listes de noms
Rechercher dans la String nom1, les noms qui ne sont pas aussi dans nom2.
Dim nom1 As String () = {" Philippe " , " Paul " }
Dim nom2 As String () = {" Paul " , " Jean " }
Dim difference = nom1. Except (nom2)
For Each name As String In difference
Console. WriteLine (name)
Next
|
Affiche 'Philippe'
V-Y-7. Link et les contrôles
Comment obtenir la liste des contrôles actifs dans un formulaire?
Dim ControlsEnabled = _
From c In Me. Controls _
Where CType (c, Control). Enabled _
Select CType (c, Control)
|
On se rend bien compte que, ici, Linq est une alternative à For Each.
V-Y-8. Inference de Type et type anonyme
Débutant, tu peux sauter!!
On a vu que Linq fonctionnait d'une manière un peu particulière. Pour mieux comprendre cela, il faut savoir qu'à partir de VB 2008 on peut utiliser l'inférence de type et les types anonymes.
Inférence de Type
Il faut pour cela que Option Infer =On (Off par défaut)
Passer par le menu 'Projet' puis 'Propriétés de..', onglet 'Compiler'
En plus des options Explicit, Compare, Strict, on peut modifier Option Infer.
L'inférence est la capacité de déduire le type d'une variable par analyse des types fournis en entrées ainsi que des opérations effectuées sur ceux-ci. C'est donc le compilateur qui déduit le type de la variable.
Dim Myname1 As String = " Rouge "
Dim Myname2 = " Vert "
|
Le passage du curseur de la souris sur Myname2 vous permet de découvrir que celui-ci est bien un type "String".
On avait dit qu'il fallait travailler avec Option Implicit = True et là on ne déclare même pas le type!!! En fait l'inférence existe afin de supporter par exemple les types anonymes ou encore LINQ.
Il existe des cas pour lesquels l'inférence de type ne se produit pas. Pour les instructions Dim locales, l'inférence de type survient uniquement lorsqu'il y a une assignation sur la ligne de déclaration. Par conséquent, pour les assignations effectuées hors de la déclaration de la variable, le compilateur supposera que le type est Object. Object est également toujours déduit comme type des membres de niveau classe, si bien que l'inférence de type ne s'applique pas aux fonctions, sous-routines, propriétés, champs de classe/structure, etc
Lorsque Option Explicit est Off , une variable locale peut être utilisée dans le code sans déclaration explicite. La variable est supposée être dans ce cas de type Object et tous les appels sont liés tardivement. L'inférence de type ne survient pas sur les variables définies implicitement.
Type anonyme
Habituellement, on peut déclarer Mycustomer, une instance de la classe Customer et renseigner une propriété .Name.
Dim MyCustomer = New Customer With {. Name = " Philippe " }
|
Grâce au type anonyme, on peut écrire:
Dim AnomyneCustomer = New With {. Name = " Philippe " }
|
Remarque= avant New il doit y avoir '=' et pas As.
Cela créer une nouvelle classe anonyme (sans nom) possédant une propriété .Name.
Les types anonymes sont surtout utilisés avec Linq:
Exemple:
Dim namePriceQuery = From prod In products _
Select prod. Name , prod. Price
|
Si products est une liste d'objets avec plein de propriétés, namePriceQuery est une collection de type anonyme qui posséde 2 propriétés: .Name et .Price .
V-Z. Les 'Region', compilation conditionnelle, 'Attributs'
Dans le code on peut ajouter des choses qui ne sont pas du code VB, mais plutôt des directives pour l'affichage, le compilateur ou le Runtime:
V-Z-1. Les Régions
Pour une meilleure visibilité, il est possible de créer des 'régions' de code. Une région peut être déroulée ou contractée.
Une région peut être déroulée: le code entre #Region et #End Region est visible (pour modifier le code par exemple):
-
#Region "Routine de Tri"
Sub QuickSort (ByVal debut As Integer, ByVal fin As Integer)
Dim pivot, gauche, droite, temp As Integer
Do
. . .
Loop Until gauche = droite
End Sub
#End Region
|
Si on clique sur le petit carré (avant #region), cela contracte la région et masque le code, on voit seulement un petit carré avec un plus et le nom de la région.
+ Routine de Tri
Cela permet de masquer une procédure en totalité.
Attention, cela ne permet pas de masquer seulement une partie du code mais la procédure entière.
Exemple:
En VB 2003, dans une Classe de formulaire, il existe une région nommée 'Code généré par le Concepteur Windows Form' qui contient le code créant les contrôles du formulaire. Ce code est habituellement caché dans une 'région' fermée.
V-Z-2. La Compilation conditionnelle
La compilation conditionnelle contrôle si les séquences de lignes sont traduites en code réel. Certaines lignes peuvent être ignorées pendant le processus de compilation.
Les instructions de compilation conditionnelle sont précédées de #
On utilise:
#if .. then
#else
#end if
|
Exemple
#const Demo = True
Class MaClasse
#if Demo then
Sub F ()
#else
Sub G ()
#end if
End Class
|
La compilation produit le résultat suivant :
Class C
Sub F ()
End Class
|
Il suffit de changer la valeur de la constante pour compiler des parties différentes de code.
Noter que #const Demo crée une constante privée accessible uniquement dans le fichier.
En VB 2005 on peut définir une constante au niveau projet avec /define
V-Z-3. Les Attributs
Les attributs peuvent être utilisés pour décrire votre code au runtime (fournir des informations supplémentaires) ou modifier le comportement de l'application au moment de l'exécution. Le Framework fournit de nombreux attributs , mais vous pouvez également créer vos propres attributs personnalisés.
Les attributs sont entre < et > en VisualBasic.
Les attributs peuvent modifier le comportement des propriétés, méthodes, classes, assemblys. Ils couvrent différents aspects comme la compilation, la sécurité, les services Web...
Exemple: <Obsolete > Avec une procédure.
Déclarons une fonction Add comme obsolète, en plus, le compilateur affiche le message: 'Sera enlevé à la prochaine version'.
On utilise donc <Obsolete > ou le nom complet de l'attribut: <System.ObsoleteAttribut>
< Obsolete (" Sera enlevé à la prochaine version " )> Function Add (a as Integer, b as Integer) as Integer
Add = a + b - c
End Function
|
Exemple:<Browsable> avec un composant.
Dans un composant, je crée une Propertie nommée 'Valide', je ne veux pas qu'elle apparaisse dans la fenêtre 'propriétés' du composant; je veux qu'elle soit accessible uniquement par code:
Imports System. ComponentModel
< Browsable (False )> Property Valide () As Integer
|
Exemple:<ToolBoxBitMap> avec un composant.
Quand on crée un composant, on désire parfois avoir une icône propre à ce composant dans la boite à outils:
< ToolBoxBitMap (" C:MonIcone " )> Public Class MaClasse
|
Exemple:<Serializable> avec une Classe.
Quand on crée une classe, on a parfois besoin qu'elle soit sérializable:
< Serializable ()> Public Class TestSimpleObject
Public member1 As Integer
Public member2 As String
Public member3 As String
Public member4 As Double
< NonSerialized ()> Public member5 As String
|
Il est possible de faire un tas de choses avec les attributs, mais cela devient vite très complexe.
V-AA. Traiter les erreurs
Il y a plusieurs types d'erreurs.
- Les erreurs de syntaxe.
- Les erreurs d'exécution.
- Les erreurs de logique.
V-AA-1. Les erreurs de syntaxe
On peut aussi les nommer 'les erreurs du compilateur', elles se produisent lorsque le compilateur Visual Basic rencontre un code non reconnaissable, erreur de saisie ou méconnaissance du langage. Comme les erreurs du compilateur empêchent un programme de s'exécuter, vous devez être averti de ces erreurs avant de tenter d'exécuter votre programme, autrement dit durant la saisie du code.
Elles surviennent donc en mode conception quand on tape le code:
Exemples:
A+ 1= B
f. ShowDialogue
2 For . . . et un seul Next
Dim i As Integer: Label. Text = i
. . . .
|
Dans ces cas VB souligne en ondulé bleu le code. Il faut mettre le curseur sur le mot souligné, l'explication de l'erreur apparaît.
Exemple: Propriété Text d'un label mal orthographiée:
Il faut les corriger immédiatement en tapant le bon code (ici 'Text').
En bas il y a aussi une fenêtre; "liste des erreurs":
Elle affiche tous les problèmes; pour atteindre le code correspondant à une de ces erreurs, double-cliquez sur une des lignes de la liste.
En VB 2005 un bouton avec point d'exclamation permet d'ouvrir une fenêtre proposant le moyen de corriger l'erreur:
Ici on met dans la propriété text d'un label un Integer, alors qu'il faut mettre une String (Option Strict est probablement égal à On); Vb montre la correction : CStr(i) converti i en String.
Si vous exécutez le programme dans l'IDE alors qu' il y a un problème, VB demande si on veut exécuter la dernière génération réussie:
Si vous tapez 'oui' VB exécute la dernière version qui a été générée correctement, mais PAS le code source actuel qui contient des erreurs!!
V-AA-2. Les erreurs d'exécution
Elles surviennent en mode Run dans l'IDE ou lors de l'utilisation de l'exécutable:
Une instruction ne peut pas être effectuée.
Quand on utilise l'exécutable: Le logiciel s'arrête brutalement, c'est très gênant!!
Pour l'utilisateur c'est un 'BUG'
Il y a 'levée d'une exception', voila ce que cela donne dans l'IDE:
Exemple: je tente d'accéder à un élément d'un tableau qui n'existe pas (l'indice est trop grand cela entraîne une exception 'OutOfRange').
En cours de test, dans l'IDE, s'il y a une exception, le logiciel s'arrête, l'instruction qui a planté apparaît en jaune et VB donne une explication.
L'erreur est:
- Soit une erreur de conception.
Exemple:
Ouvrir un fichier qui n'existe pas (On aurait du vérifier qu'il existe avant de l'ouvrir!).
Division par zéro.
Utiliser un index d'élément de tableau supérieur au nombre d'élément:
Envoyer un mauvais paramètre à une fonction.
- Soit une erreur de l'utilisateur.
Exemple: On lui demande de taper un chiffre, il tape une lettre ou rien puis valide.
Il faut toujours vérifier ce que fait l'utilisateur et prévoir toutes les possibilités.
Exemple: si je demande à l'utilisateur de taper un nombre entre 1 et 10, il faut:
Vérifier qu'il a tapé quelque chose.
Que c'est bien un chiffre (pas des lettres).
Que le chiffre est bien entre 1 et 10.
Sinon il faudra reposer la question.
A-Capter les erreurs avec Try Catch Finally:
Plutôt que de laisser le logiciel 'planter', je vais anticiper et essayer de capter l'erreur au niveau des lignes de code qui peuvent la provoquer.
Avant l'instruction supposée provoquer une erreur indiquez: Essayer l'instruction (Try), si une erreur se produit Intercepter l'erreur (Catch) puis poursuivre (après Finally).
Try
Catch
Finally
End Try
|
Il faut pour que cela fonctionne avoir tapé au préalable Imports System.IO
Il est possible d'utiliser Catch pour récupérer l'objet 'Exception' qui est généré par l'erreur.
Cet objet Exception à des propriétés:
Message qui contient le descriptif de l'erreur.
Source qui contient l'objet qui a provoqué l'erreur....
ex.Message contient donc le message de l'erreur.
Cet objet généraliste Exception( de l'espace IO) a aussi des classes dérivées:
-StackOverFlowException
-FileNotFoundException
-EndOfStreamException
-FileLoadException
-PathTooLongException.
Enfin une exception peut provenir de l'espace System: ArgumentExceptions; ArithmeticException:
-DivideByZeroException.....
Il est possible d'écrire plusieurs instructions Catch avec pour chacune le type de l'erreur à intercepter. (Faisant partie de la classe Exceptions)
Exemple:
On ouvre un fichier par StreamReader , comment intercepter les exceptions suivantes?
Répertoire non valide
Fichier non valide
Autre.
Try
sr= New StreamerReader (NomFichier)
Catch ex As DirectoryNotFoundException
MsgBox (" Répertoire invalide " )
Catch ex As FileNotFoundException
MsgBox (" Fichier invalide " )
Catch ex As Exception
MsgBox (ex. Message )
End Try
|
Noter que le dernier Catch intercepte toutes les autres exceptions.
On peut encore affiner la gestion par le mot clé When qui permet une condition.
Catch ex As FileNotFoundException
When ex. Message . IndexOf (" Mon Fichier.txt " ) > 0
MsgBox (" Impossible d'ouvrir Mon Fichier.txt " )
|
Si le texte "Mon Fichier.txt" est dans le message, affichez que c'est lui qui ne peut pas être ouvert.
Exit Try permet de sortir prématurément. Quitte immédiatement le bloc Try ou Catch dans lequel il est. L'exécution continue avec le bloc Finally s'il y en a un, ou avec l'instruction qui suit End Try.
B-Capter les erreurs avec On error :
On peut aussi utiliser la méthode Visual Basic:
On Error Goto permet en cas d'erreur de sauter à une étiquette (un emplacement dans le code) emplacement ou une portion de code traite l'erreur.
On peut lire le numéro de l'erreur qui s'est produite, ce numéro est dans Err.Number.
Err.Description contient le texte décrivant l'erreur. Err.Source donne le nom de l'objet ou de l'application qui a crée l'erreur.
Quand l'erreur est corrigée, on peut revenir de nouveau à la ligne qui a provoqué l'erreur grâce à Resume ou poursuivre à la ligne suivante grâce à Resume Next
Exemple:
On Error GoTo RoutinedErreur
Dim x As Integer = 33
Dim y As Integer = 0
Dim z As Integer
z = x / y
RoutinedErreur :
Select Case Err . Number
Case 6
y = 1
Case Else
End Select
Resume
|
Pour arrêter la gestion des erreurs il faut utiliser:
Parfois on utilise une gestion hyper simplifiée des erreurs:
Si une instruction 'plante', la sauter et passer à l'instruction suivante, pour cela on utilise:
On Error Resume Next
Exemple: On veut effacer un fichier
On Error Resume Next
Kill (MonFichier)
On Error goto 0
|
Ainsi , si le fichier n'existe pas , cela ne plante pas (on aurait pu aussi vérifier qu'il existe avant de l'effacer!!).
On Error Gosub n'existe plus.
 |
On Error est moins performant que Try Catch et surtout il ralentit le code+++: si nécessaire utiliser Try Catch.
|
En résumé: pour éviter les erreurs d'exécution il est donc possible:
- D'écrire du code gérant le problème, contrôlant les actions de l'utilisateur..
Exemple: on demande à l'utilisateur de saisir un nombre dans TextBox1 puis de cliquer sur Button3
Si l'utilisateur a tapé une lettre au lieu d'un chiffre, le prévenir.
Private Sub Button3_Click
If String . IsNullOrEmpty (TextBox1. Text ) Then
MsgBox (" Tapez quelque chose " )
Else
If Not IsNumeric (TextBox1. Text ) Then
MsgBox (" Tapez un chiffre " )
End If
End If
End Sub
|
- Une autre alternative est de capter l'erreur.
Exemple: on demande à l'utilisateur de saisir un nombre dans TextBox1 puis de cliquez sur Button3
Convertir le texte tapé en Integer, on sait que si la conversion est impossible (pas de texte tapé ou texte non numérique) une exception invalidCastException sera levée et le programme 'plantera'. On écrit donc avant l'instruction CType un Try pour capter l'erreur:
Tester s'il y a une erreur, la capter.
Private Sub Button3_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) Handles Button3. Click
Dim i As Integer
Try
i = CType (TextBox1. Text , Integer)
Catch
MsgBox (" saisir un nombre " )
End Try
End Sub
|
V-AA-3. Les erreurs de logique
Le programme fonctionne, pas d'erreurs apparentes, mais les résultats sont erronés, faux.
Il faut faire des tests dans les conditions réelles avec des données courantes, mais aussi avec des données remarquables (limites supérieures, inférieures, cas particuliers..) pour voir si les résultats sont cohérents et exacts.
Une fois l'erreur trouvée, il faut en déterminer la cause et la corriger.
Ou bien elle est évidente à la lecture du code ou bien elle n'est pas évidente et c'est l'horreur.
Dans ce dernier cas il faut analyser le fonctionnement du programme pas à pas, instruction par instruction en surveillant la valeur des variables.(voir la rubrique débogage )
Les erreurs les plus communes sont:
Utilisation d'un mauvais nom de variable (La déclaration obligatoire des variables évite cela)
Erreur dans la portée d'une variable.
Erreur dans le passage de paramètres (Attention au By Val et By Ref)
Erreur dans la conception de l'algorithme.
...
Quelques règles permettent de les éviter: voir Règles de bonne programmation.
V-AA-4. Les Tests
Il faut donc toujours tester le fonctionnement du programme de multiples fois:
On fera des:
- Tests unitaires: qui testeront les procédures, les classes une à une sans tester la totalité du programme.
- Tests de composants et d'intégration: qui testeront plusieurs procédures ou classes fonctionnant ensemble.
- Tests de régression: c'est la répétition des test précédents afin de voir si une modification ou un ajout n'entraîne pas de nouvelles erreurs qui n'existaient pas.
- Tests système: test sur le logiciel dans sa version finale.
Les tests détecteront les erreurs, le débogage permettra de trouver la cause et de corriger l'erreur.
 |
Il faut avoir une armée de Bêta-testeurs.
|
Les sources présentés sur cette page sont libres de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © .
Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu :
textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts.
Cette page est déposée à la SACD.
|