-
Les erreurs anticipées : ce sont les erreurs que votre programme peut anticiper, comme tenter de lire un fichier qui n'existe pas, ou tenter d'ouvrir une connexion avec une chaîne de connexion invalide.
-
Les erreurs non anticipées : ce sont les erreurs qui surviennent suite à des conditions inattendues, telles qu'une erreur de programmation ou une erreur de donnée.
-
Les violations de règles métier : ce peuvent être des erreurs d'entrée de données telles que la saisie de caractères alphabétiques dans un champ numérique, ou ce peuvent être des problèmes de logique métier plus complexes comme tenter de supprimer une ligne de commande pour une commande qui aurait déjà été envoyée.
Cependant, On Error Goto a ses limites. Sa syntaxe de
style Goto rend vos routines structurellement complexes. Et si vous
oubliez de sortir de la routine avant la gestion de l'erreur tout en
bas, il était facile de tomber accidentellement du code de la routine
dans la gestion de l'erreur. Il était difficile de garder un code
propre pouvant exécuter tous les cas (sans se soucier de savoir si une
erreur survenait ou non).
Visual Basic .NET possède une riche
palette de fonctionnalités qui fournissent toutes les fonctionnalités
de On Error Go sans ses limitations. En fait, Visual Basic .NET
supporte On Error Goto à travers la bibliothèque Microsoft Visual Basic
.NET Compatibility. Cette bibliothèque permet de conserver certaines
fonctionnalités de Visual Basic 6.0 en Visual Basic .NET afin de
simplifier le processus de migration. Les fonctionnalités de cette
bibliothèque ne doivent être utilisées que pour la migration.
Capturer les Exceptions
Par exemple, de nombreuses applications utilisent un formulaire ou une page de login pour contrôler l'accès à l'application et à ses fonctions. Le code pour valider le login est ainsi exécuté quand l'utilisateur clique sur le bouton login :
CODE :
Private Sub cmdLogin_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cmdLogin.Click
Dim oUser As User()
Dim bValid as Boolean
oUser = New User()
bValid = oUser.ValidateLogin(txtUserName.Text, txtPassword.Text)
If bValid then
DialogResult = DialogResult.OK
End If
oUser.Dispose
oUser = Nothing
End Sub
Il y a plusieurs endroits dans ce code où une exception pourrait survenir. La ligne de code qui crée la nouvelle instance à partir de la classe User pourrait générer une erreur non anticipée si l'instance ne pouvait pas être créée pour une raison quelconque. La méthode ValidateLogin pourrait générer des exceptions anticipées (comme une chaîne de connexion invalide), des exceptions non anticipées (comme un champ de table ou une procédure stockée manquante), ou des violations de règle métier (comme passer un nom d'utilisateur vide).
Au lieu d'ajouter un On Error Goto pour capturer ces exceptions, on peut utiliser un bloc Try/Catch .NET. La syntaxe Try/Catch facilite la capture et le traitement des exceptions de manière structurée. C'est la raison pour laquelle la gestion des exceptions .NET est souvent mentionnée comme une gestion des exceptions structurée (structured exception handling, SEH).
Un bloc Try/Catch pourrait être ajouté au code de la manière suivante :
CODE :
Private Sub cmdLogin_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cmdLogin.Click
Dim oUser As User()
Dim bValid as Boolean
Try
oUser = New User()
bValid = oUser.ValidateLogin(txtUserName.Text, txtPassword.Text)
If bValid then
DialogResult = DialogResult.OK
End If
oUser.Dispose
oUser = Nothing
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Si une exception intervient dans le bloc Try, le bloc Catch
capture l'exception et le code à l'intérieur du bloc Catch s'exécute.
Dans ce cas, la capture va saisir chaque exception, assigner
l'exception à la variable ex, et afficher une boîte de message
contenant le message d'exception. Si aucune exception ne survient, le
bloc de code Catch est ignoré.
Si vous examinez l'exemple précédent,
vous noterez que le code pour se débarrasser de l'instance ne sera pas
exécuté si une exception intervient. Pour corriger cela, le code pourra
être répété dans le bloc Catch, mais cela signifie qu'il y a
duplication de code.
Une meilleure approche pourrait être d'utiliser
le bloc optionnel Finally à l'intérieur du bloc Try/Catch de la manière
suivante :
CODE :
Le code dans le bloc Finally sera exécuté après l'exécution complète du bloc Try, après l'exécution du bloc Catch, ou après l'exécution de toutes instructions Return dans les blocs Try ou Catch. Tout code qui a besoin d'être exécuté avant de quitter la routine doit être ajouté au bloc Finally.Private Sub cmdLogin_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cmdLogin.Click
Dim oUser As User()
Dim bValid as Boolean
Try
oUser = New User()
bValid = oUser.ValidateLogin(txtUserName.Text, txtPassword.Text)
If bValid then
DialogResult = DialogResult.OK
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
oUser.Dispose()
oUser = Nothing
End Try
End Sub
Notez la manière dont la déclaration de l'objet User a été faite en dehors du bloc Try. C'est indispensable si la variable objet doit être accessible à la fois à partir du bloc Try et du bloc Finally parce que .NET a des variables de portée bloc.
-
Les variables globales accessibles par l'application entière
-
Les variables module accessibles dans le fichier code (form, classe ou module) dans lequel elles étaient déclarées
-
Les variables locales accessibles seulement dans la routine dans laquelle elles étaient déclarées.
En
.NET, il y a un quatrième type de portée : la portée bloc. Les
variables déclarées à l'intérieur d'un bloc tel qu'un bloc Try ou un
bloc For/Next ne sont accessibles qu'à l'intérieur du bloc.
Si la
déclaration de l'objet User a été faite à l'intérieur du bloc Try, le
bloc Finally ne pourra pas faire référence à la variable. Les variables
objets qui auront besoin d'être accédées dans le bloc Finally devront
être déclarées en dehors du bloc Try.
Lever les Exceptions
Lorsque vous écrivez vos
routines, vous devez suivre les mêmes règles et lever des exceptions
quand une hypothèse implicite est violée. Pour lever une exception,
utilisez l'instruction Throw et lever une nouvelle instance de la
classe exception appropriée (voir l'aide en ligne pour la liste des
exceptions .NET que vous pouvez lever).
Par exemple, la méthode
ValidateLogin fait l'hypothèse qu'elle devrait recevoir en paramètres
des valeurs non vides. Si les valeurs sont vides, elle doit lever une
exception ArgumentOutOfRange.
CODE :
Public Function ValidateLogin(ByVal sUserName As String, _
ByVal sPassword As String) As Boolean
If sUserName.length=0 OrElse sPassword.Length=0 Then
Throw New ArgumentOutOfRangeException("Usager et Mot de passe sont requis")
End If
' Code de validation du login
Return True
End Function
L'instruction Throw crée une nouvelle instance de ArgumentOutOfRangeException et définit le texte du message. Quand cette instruction est exécutée, l'exception est levée.
Le
code qui suit l'instruction Throw n'est pas exécuté, la runtime .NET
cherche plutôt un bloc Try/Catch. Si le code en cours n'est pas un bloc
Try, la runtime .NET examine la pile d'appels pour voir si le code qui
a appelé cette méthode n'est pas un bloc Try. Si elle trouve un bloc
Try, elle cherche alors un bloc Catch associé. Si la runtime .NET
trouve un bloc Try/Catch approprié, elle exécute alors le code dans le
bloc Catch. Sinon, elle affiche le message d'exception non gérée et
termine l'application.
A noter que comme la runtime .NET cherche des
blocs Try associés de la pile d'appels, elle exécutera tout code dans
le bloc Finally associé avant de continuer la pile d'appels.
En plus
de lever des exceptions .NET, vous pouvez vouloir définit vos propres
exceptions. Dans l'exemple de login, en plus de lever
ArgumentOutOfRangeException, vous pouvez vouloir lever une exception
spécifique si le nom d'utilisateur n'est pas valide et une exception
spécifique différente si le mot de passe est invalide.
Pour créer
une exception spécifique, vous pouvez créer votre propre classe
d'exception. Pour s'assurer qu'elle se comporte comme une exception
.NET, votre nouvelle classe d'exception doit hériter d'une des classes
d'exception .NET. La classe recommandée à utiliser pour votre héritage
est la classe ApplicationException . Par exemple, la classe UsernameNotFoundException devrait ressembler à cela :
CODE :
Public Class UsernameNotFoundException : Inherits ApplicationException
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal message As String)
MyBase.New(message)
End Sub
Public Sub New(ByVal message As String, ByVal innerEx As Exception)
MyBase.New(message, innerEx)
End Sub
End Class
La nouvelle classe n'hérite d'aucun des constructeurs de la classe héritée ; d'où le besoin pour cette classe d'avoir ses propres constructeurs. La classe ApplicationException supporte trois constructeurs :
-
Un sans paramètre
-
Un avec juste le paramètre message
-
Un avec à la fois le message et une exception interne
Le
dernier constructeur est utilisé dans le cas où le code capture une
exception et la lève à son tour comme une autre exception, mais veut
conserver les informations de l'exception d'origine.
Vous pouvez
aussi ajouter vos propres propriétés et méthodes à votre nouvelle
classe d'exception. Par exemple, en ajoutant une propriété username à
votre classe d'exception vous pouvez journaliser toutes les exceptions
et inclure le nom de l'utilisateur qui a eu l'exception. La routine
peut lever des exceptions spécifiques de la manière suivante.
CODE :
Public Function ValidateLogin(ByVal sUserName As String, _
ByVal sPassword As String) As Boolean
If sUserName.length=0 OrElse sPassword.Length=0 Then
Throw New ArgumentOutOfRangeException("Usager et mot de passe invalide")
End If
' Code de recherche de l'usager
If iUserRecordID = 0 Then
Throw New UsernameNotFoundException("Usager invalide")
End If
' Code de récupération du mot de passe de l'usager
If sPassword <> sUserRecordPassword Then
Throw New PasswordInvalidException("Mot de passe invalide")
End If
Return True
End Function
Cette routine lève à la fois une exception .NET et une
exception spécifique si une quelconque hypothèse implicite de la
routine est violée.
Capturer les Exceptions spécifiques
Private Sub cmdLogin_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cmdLogin.Click
Dim oUser As User()
Dim bValid as Boolean
Try
oUser = New User()
bValid = oUser.ValidateLogin(txtUserName.Text, txtPassword.Text)
If bValid then
DialogResult = DialogResult.OK
End If
Catch ex As UsernameNotFoundException
MessageBox.Show(ex.Message)
txtUserName.Focus()
Catch ex As PasswordInvalidException
MessageBox.Show(ex.Message)
txtPassword.Focus()
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
oUser.Dispose()
oUser = Nothing
End Try
End Sub
La gestion des exceptions dans Visual Basic a changé, oui mais elle s'est améliorée. Vous pouvez construire maintenant des gestionnaires d'exception structurés pour capturer tous types d'erreur ou de violations de règles métier. Avec Try/Catch/Finally et la capacité à hériter vos propres classes d'exception à partir des exception .NET, vous pouvez jeter aux oubliettes les On Error Goto !
{mos_fb_discuss:no_discuss}






