Paru le 02 février 2005 | Dernière mise à jour le 28 février 2005
Cet article examine les nombreuses améliorations apportées à Visual Basic 2005 et propose pour les illustrer quelques extraits de code simples. Les fonctionnalités couvertes incluent notamment les commentaires XML, les génériques, le mot-clé Global, les types partiels, le mot My, etc. (20 pages imprimées)
Remarque : Cet article et les exemples de code s'appuient sur une version préliminaire de Microsoft Visual Studio 2005, dont le nom de code était « Whidbey ». Toutes les informations contenues ici peuvent faire l'objet de modifications.
Sur cette page
Introduction
My
Commentaires XML
Génériques
Instruction Using
Instruction Continue
Mot Global
Opérateur IsNot
Instruction TryCast
Surcharge des opérateurs et opérateurs de conversion
Accessibilité des mécanismes d'accès aux propriétés
Accesseurs aux événements personnalisés
Types partiels
Événements de niveau application
Types non signés
Instances par défaut
Avertissements du compilateur
Limites de tableau explicites
Conclusion
Introduction
La version publique bêta de Visual Studio 2005 donne un aperçu stable de Visual Basic 2005 dans lequel les nouvelles fonctionnalités ont été construites de façon quasi définitives, de telle sorte que la version RTM ne devrait contenir que peu de modifications. Naturellement, certains éléments changeront mais vous pouvez globalement attendre du produit fini qu'il ressemble fort à la version bêta 1. Toutefois, je vous conseille ne de pas installer la version bêta sur une machine de production mais de l'exécuter plutôt dans le périmètre de sécurité d'une image PC virtuelle Microsoft.
Les principales modifications du langage Visual Basic concernent le mot-clé My, les commentaires XML et les génériques. Plusieurs instructions nouvelles, notamment Using, Continue et TryCast, ainsi que le mot-clé Global, comblent certaines lacunes sur le plan logique. Par ailleurs, des améliorations structurelles ont été apportées concernant l'accessibilité des mécanismes d'accès aux propriétés, les accesseurs aux événements personnalisés, les types partiels et les événements de niveau application. La surcharge des opérateurs et les opérateurs de conversion sont des nouveautés, ainsi que l'opérateur IsNot. D'autres modifications utiles portent notamment sur les types non signés, les instances par défaut de formulaire, les avertissements du compilateur et les limites de tableau explicites.
La première fois que vous lancez Visual Studio 2005, vous êtes invité à sélectionner vos paramètres IDE préférentiels. Ces paramètres contrôlent les fonctionnalités telles que les mappages de clé IDE, la disposition des fenêtres et la mise en forme du code dans l'éditeur de code. Vous pouvez modifier ces paramètres à tout moment à partir du menu Tools | Import/Export Settings comme indiqué dans la figure 1. Vous pouvez importer des paramètres par défaut à partir d'un autre langage de programmation ou des fichiers de paramètres personnalisés utilisés par les développeurs de votre entreprise.
Figure 1. Importation de paramètres personnalisés pour normaliser l'environnement de développement dans votre entreprise
My
Lorsque les développeurs ont migré de Visual Basic 6.0 et les versions antérieures vers .NET, ils ont dû tenir compte de la taille non négligeable de la plate-forme .NET et du nombre de classes présentes dans sa hiérarchie d'espaces de noms. Les objets d'environnement et d'application communément utilisés figurent dans la bibliothèque de classes de base (BCL, Base Class Library) de .NET Framework et il faut du temps pour apprendre à les repérer. La nouvelle hiérarchie My de Visual Basic 2005 accélère et simplifie le développement d'applications en permettant un accès pratique et logiquement organisé aux nombreuses classes souvent utilisées.
My se décline sous deux formes possibles :
-
des éléments qui fournissent des raccourcis structurés pour accéder aux classes Framework,
-
un ensemble d'objets dynamiques qui se créent lorsque vous ajoutez des formulaires, des paramètres, des ressources ou des services Web dans vos projets.
Les raccourcis My sont avant tout un moyen pour accélérer l'accès aux objets de la BCL couramment utilisés. Les raccourcis My de niveau supérieur sont My.Application, My.Computer et My.User qui contiennent chacun leur propre hiérarchie d'objets. Par exemple, l'objet My.User expose Audio, FileSystem, Keyboard, Mouse, Network, Registry, pour ne citer que ceux-là :
Dim sVar As String
sVar = My.User.Identity.Name
sVar = My.Computer.Info.OSFullName
sVar = My.Application.CommandLineArgs.Count.ToString
Les objets dynamiques My sont automatiquement remplis par Visual Basic lorsque vous ajoutez des formulaires, des ressources, des paramètres ou des services Web dans votre projet. My.Resources et My.Settings sont particulièrement intéressants du fait que le compilateur Visual Basic génère des références de variables fortement typées lorsque vous insérez des ressources et des paramètres dans un projet.
Dans l'Explorateur de solutions, double-cliquez sur My Project afin d'ouvrir le concepteur d'applications. Cliquez sur Settings dans la liste d'onglets située à gauche, comme indiqué dans la figure 2.
Figure 2. Concepteur d'applications avec l'onglet Settings affiché. Le volet de la liste d'erreurs contient les erreurs, les avertissements et les messages et il est désormais séparé de la liste des tâches.
Ajoutez un nom de paramètre tel que MaxInputValue de type Integer dans la portée User avec la valeur 100. Désormais, vous pouvez immédiatement vous référer à ce paramètre avec un objet de type fort dans votre code en utilisant la fonction IntelliSense, comme le montre la figure 3.
Figure 3. Exemple de fenêtre contextuelle IntelliSense pour une valeur de paramètre que vous créez dans le concepteur d'applications Settings.
En haut à droite du concepteur Settings s'affiche un lien nommé View Code. Cliquez sur ce lien pour visualiser le fichier nommé MySettings_user.vb. Ce fichier est une classe partielle dans laquelle vous pouvez ajouter du code visant à gérer les événements de paramètres afin de mettre à jour l'état de votre application à mesure que vos paramètres changent (pour plus d'informations, reportez-vous à la section concernant les types partiels).
Partial Public Class MySettings
'...
End Class
Trois événements MySettings sont exposés ici :
-
PropertyChanged
-
SettingChanging
-
SettingsSaving
L'interface Settings de l'application est enfichable, ce qui signifie que vous pouvez définir la manière dont vos paramètres sont enregistrés en implémentant ces routines d'événement.
Vous obtenez le même typage fort avec les ressources que vous ajoutez dans votre projet. Si vous déposez une image nommée Happy.bmp dans la zone Images du concepteur Resources, vous pouvez vous y référer dans le code en vous servant de l'appellation My.Resources.Happy. Happy est de type Bitmap et, par conséquent, vous n'avez pas à effectuer de conversion depuis un type Objet ou Image pour l'utiliser dans le code. La fonction IntelliSense est aussi immédiatement opérationnelle lorsque vous entrez Happy dans votre code. Par exemple :
PictureBox1.Image = My.Resources.HAPPY
Cette ligne de code affecte l'objet bitmap à la propriété Image d'un objet PictureBox. La figure 4 reproduit la fenêtre contextuelle IntelliSense indiquant que l'objet est de type Bitmap.
Figure 4. L'insertion par glisser-déplacer d'une image bitmap dans l'onglet Resources du concepteur d'applications fournit un objet fortement typé immédiatement utilisable dans votre code.
À mesure que vous ajoutez des formulaires et des services Web dans votre projet, l'objet My est dynamiquement alimenté avec des instances par défaut fortement typées de ces objets et vous pouvez vous y référer dans le code.
Comme vous le constatez, My facilite considérablement la recherche des classes de la BCL relatives aux applications et à l'environnement et offre un accès immédiat et fortement typé à des paramètres, des ressources ou autres objets que vous ajoutez dans vos projets selon vos besoins. Pour les développeurs Visual Basic, quel que soit leur niveau de pratique, ces améliorations sont essentielles en termes de productivité.
Commentaires XML
Les commentaires XML vous permettent d'ajouter une documentation structurée dans votre code, avantage dont les développeurs disposaient déjà dans C# et qu'ils attendaient impatiemment dans Visual Basic. Les commentaires XML peuvent décrire divers éléments du code, y compris les classes, les champs, les méthodes et les énumérations.
Si vous créez un commentaire XML décrivant une fonctionnalité du code, vous obtenez immédiatement par le biais d'IntelliSense des paramètres ainsi que le type de retour lorsque vous entrez la fonctionnalité en question dans l'éditeur. Supposons que vous ayez un prototype de fonction avec la signature suivante :
Private Function GetCustomerData(ByVal CustomerCode As String) _
As DataSet
Placez le point d'insertion sur la ligne qui précède la déclaration de fonction et tapez trois caractères apostrophe. Visual Basic génère un modèle de commentaire XML correspondant à la déclaration de fonction, que vous pouvez parcourir et remplir comme un formulaire. Supposons que pour votre fonction, vous remplissiez le modèle de commentaire comme suit :
''' <summary>
''' Returns a DataSet for a single customer.
''' </summary>
''' <param name="CustomerCode">Customer Code as String.</param>
''' <returns>DataSet for the supplied CustomerCode.</returns>
''' <remarks>Resides in the application's data layer.</remarks>
Lorsque vous tapez ce nom de fonction ailleurs dans votre code, vous obtenez grâce à IntelliSense le résumé de la fonction, les paramètres et la valeur de retour, comme le montre la figure 5.
Figure 5. Cette info-bulle affiche les données immédiatement renvoyées par IntelliSense lorsque vous ajoutez des commentaires XML dans vos éléments de code.
Il s'agit d'une fonctionnalité clé dans les environnements de travail en équipe et en entreprise. Vous pouvez générer une documentation du code à partir des commentaires XML structurés que vous avez insérés dans les fichiers source. Par ailleurs, un développeur ou un architecte d'applications peut créer des prototypes de fonction et les commenter avant de les mettre en œuvre. À mesure que les développeurs écrivent du code en utilisant les objets de prototype, IntelliSense les guide dans l'utilisation correcte des fonctionnalités.
Les commentaires XML sont traités par le compilateur comme partie intégrante du code. Les valeurs des balises de commentaires sont signalées en tant que telles par une couleur ; si vous réduisez le contenu d'un commentaire XML, seule la valeur de la balise de résumé (summary) apparaît à la place du modèle complet (voir la figure 6).
Figure 6. Les commentaires XML sont entièrement intégrés dans le compilateur et la fenêtre de code. Le commentaire XML sur la fonction FillDataGrid est réduit et seule sa ligne de résumé apparaît.
Si, dans le prototype de fonction, vous remplacez le nom du paramètre CustomerCode par CustomerID, le compilateur ajoute une annotation en vert sous la balise <param name="CustomerCode"> pour signaler que les deux noms ne correspondent pas (pour plus d'informations, reportez-vous à la section Avertissements du compilateur).
Visual Basic génère automatiquement un fichier de documentation XML lorsque vous créez le projet. Ce fichier apparaît dans le répertoire de sortie de l'application sous le nom AssemblyName.xml. Du fait qu'il s'agit d'un fichier XML, vous pouvez aisément le convertir dans d'autres formats de sortie. Les commentaires XML facilitent grandement la génération d'une documentation pour votre code, aussi bien sous la forme d'éléments IntelliSense pendant le codage que comme documentation proprement dite une fois que vous avez bâti votre application.
Génériques
La bibliothèque BCL fournit désormais l'espace de noms System.Collections.Generic, qui contient plusieurs classes définissant des collections génériques. Elles sont dites génériques car au niveau de la déclaration, vous spécifiez un espace réservé pour les objets contenus au lieu d'indiquer un type. Vous attribuez aux objets stockés un type spécifique uniquement lorsque vous créez une instance de la collection.
Les génériques permettent un gain de temps considérable. S'il vous est déjà arrivé de constituer des collections personnalisées, vous n'ignorez pas la quantité de code mis en œuvre. Dans Visual Basic, les génériques permettent de créer l'équivalent d'une collection personnalisée avec une ligne de code. Vous n'avez plus besoin de créer des collections personnalisées distinctes pour chaque type d'objet à stocker. Il suffit d'indiquer le type souhaité lorsque vous instanciez la collection générique.
Le plus simple pour comprendre le fonctionnement des génériques est de l'illustrer par un exemple. Prenons une classe Customer simple avec deux propriétés publiques (présentées comme des variables publiques par souci de brièveté) :
Public Class Customer
Public Name As String
Public CreditLimit As Decimal
Public Sub New(ByVal CustomerName As String, _
ByVal CustCreditLimit As Decimal)
Name = CustomerName
CreditLimit = CustCreditLimit
End Sub
End Class
Vous pouvez déclarer une liste de clients (Customers) en utilisant la classe List de la collection générique comme suit :
Dim Customers As New System.Collections.Generic.List(Of Customer)
Avec cette unique ligne de code, vous venez de déclarer une liste fortement typée qui contient uniquement des types Customer et permet d'accéder via IntelliSense aux objets Customer qu'elle contient. Tout aussi simplement, vous dressez une liste d'objets Product ou Order en créant un ensemble de collections personnalisées sans écrire tout le code correspondant à chaque type. Vous pouvez désormais écrire du code semblable à celui-ci :
Dim custA As New Customer("CustA", 1000)
Customers.Add(custA)
Dim custB As New Customer("CustB", 2000)
Customers.Add(custB)
For Each c As Customer In Customers
MessageBox.Show("Customer: " & c.Name & _
", limit: " & c.CreditLimit)
Next
'compile error: Product cannot be converted to Customer
Dim prodA As New Product("ProdA", CDec(29.95))
Customers.Add(prodA)
L'utilisation de collections génériques améliore encore vos performances car les objets stockés sont fortement typés et ne sont pas gardés en interne comme type Object.
Il existe d'autres génériques disponibles dans l'espace de noms System.Collections.Generic. Par exemple, la collection Dictionary(of K,V) permet de spécifier des types pour les clés et les valeurs. Les collections génériques LinkedList(of T) et Stack(of T) se comportent comme des piles et des listes liées standard, si ce n'est que vous avez la possibilité de préciser les sortes d'objets qu'elles vont contenir.
Vous pouvez créer vos propres types génériques en utilisant la nouvelle syntaxe de déclaration des types génériques. Considérez une classe Comparer qui permet de comparer différentes sortes d'objets :
Public Class Comparer(Of itemType)
'...
End Class
Vous pouvez définir dans une liste d'éléments séparés par des virgules des espaces réservés pour plusieurs types. Vous pouvez aussi définir des contraintes restreignant le type de classes qui peuvent être fournies à la collection générique lorsqu'elle est instanciée :
Public Class Comparer(Of itemType As IComparable)
'...
End Class
Cette contrainte garantit la création d'instances Comparer(of T) uniquement avec des classes implémentant l'interface IComparable. Il est possible d'appliquer plusieurs contraintes à la déclaration de la classe.
Par exemple, prenons la classe Customers élargie qui implémente IComparable :
Public Class Customer
Implements IComparable
Public Name As String
Public CreditLimit As Decimal
Public Sub New(ByVal CustomerName As String, _
ByVal CustCreditLimit As Decimal)
Name = CustomerName
CreditLimit = CustCreditLimit
End Sub
Public Function CompareTo(ByVal obj As Object) As Integer _
Implements IComparable.CompareTo
Dim c As Customer = CType(obj, Customer)
If CreditLimit > c.CreditLimit Then Return 1
If CreditLimit < c.CreditLimit Then Return -1
Return 0
End Function
End Class
Une classe Product similaire est implémentée, sauf que la fonction CompareTo compare les prix des produits au lieu des limites de crédit :
Public Class Product
Implements IComparable
Public Name As String
Public Price As Decimal
Public Sub New(...)...
Public Function CompareTo(...)...
End Class
À présent, la classe Comparer propose l'opération de comparaison générique :
Public Class Comparer(Of itemType As IComparable)
Public Function GetLargest(ByVal Item1 As itemType, _
ByVal Item2 As itemType) As itemType
Dim i As Integer = Item1.CompareTo(Item2)
If i > 0 Then Return Item1
If i < 0 Then Return Item2
Return Nothing
End Function
End Class
Vous pouvez maintenant instancier Comparers avec des objets de types différents :
Dim pc As New Comparer(Of Product)
Dim prod1 As New Product("LittleOne", 10)
Dim prod2 As New Product("BigOne", 100)
Dim lp As Product = pc.GetLargest(prod1, prod2)
MessageBox.Show("The more expensive product is: " & lp.Name)
Dim cc As New Comparer(Of Customer)
Dim cust1 As New Customer("SmallCo", 1000)
Dim cust2 As New Customer("LargeCo", 5000)
Dim lc As Customer = cc.GetLargest(cust1, cust2)
MessageBox.Show("The customer with a higher limit is: " & lc.Name)
Sans les génériques, vous devriez définir une classe de comparaison pour chaque type d'objet à comparer (par exemple, ProductComparer et OrderComparer).
Les génériques peuvent réduire considérablement le travail de codage dans de nombreuses situations courantes. N'hésitez pas à utiliser des génériques lorsque vous avez plusieurs classes qui varient uniquement en fonction du type d'objet sur lequel elles opèrent.
Instruction Using
L'instruction Using est un raccourci pour obtenir un objet, exécuter le code qui l'accompagne et le libérer immédiatement. Avec un certain nombre d'objets du Framework, tels que des graphiques, des gestionnaires de fichier, des ports de communication et des connexions SQL, il convient de libérer les objets que vous créez pour éviter des déperditions de mémoire dans vos applications. Supposons que vous vouliez dessiner un rectangle à l'aide d'un objet Brush :
Using g As Graphics = Me.CreateGraphics()
Using br As System.Drawing.SolidBrush = _
New SolidBrush(System.Drawing.Color.Blue)
g.FillRectangle(br, New Rectangle(30, 50, 230, 200))
End Using
End Using
Vous vous débarrasserez probablement du graphique et des objets Brush une fois que vous les aurez utilisés, ce qui est très simple avec l'instruction Using. En effet, son emploi permet un traitement plus direct que le fait d'utiliser Try / Catch puis de libérer l'objet dans le bloc Finally comme vous deviez le faire dans Visual Basic .NET.
Instruction Continue
L'instruction Continue saute à l'itération suivante d'une boucle, ce qui rend la logique de cette dernière plus concise et plus facile à lire :
Dim j As Integer
Dim prod As Integer
For i As Integer = 0 To 100
j = 0
While j < i
prod = i * j
If prod > 5000 Then
'skips to the next For value
Continue For
End If
j += 1
End While
Next
L'instruction Continue est très claire et elle facilite vraiment l'échappement de la boucle interne sans recourir à un libellé et à une instruction goto. L'instruction Continue opère sur les boucles For, While et Do.
Mot Global
Le mot-clé Global permet d'accéder à l'espace de noms racine (vide), tout en haut de la hiérarchie d'espaces de noms. Jusqu'à présent, il était impossible de définir un espace de noms System.IO dans la hiérarchie d'espaces de noms de votre entreprise :
Namespace MyCompany.System.IO
Ce faisant, vous auriez mélangé toutes les références à l'espace de noms System du framework au sein de votre application. Désormais, vous pouvez utiliser le mot-clé Global pour éviter toute ambiguïté au niveau des espaces de noms :
Dim myFile As Global.System.IO.File
Le mot-clé Global est particulièrement utile dans la génération de code, lorsque vous voulez être absolument certain que les références aux espaces de noms générées pointent bien sur l'espace qui vous intéresse. Vous verrez qu'en principe, Visual Basic va utiliser lui-même le mot-clé Global dans tout le code généré.
Opérateur IsNot
L'opérateur IsNot offre une contrepartie à l'opérateur Is. Au lieu de vous obliger à vérifier, comme bien souvent, que l'objet a été instancié pour que vous puissiez le référencer :
If Not myObj Is Nothing Then
L'opérateur IsNot vous permet d'établir une comparaison directe, éliminant l'opérateur Not :
If myObj IsNot Nothing Then
De même, vous pouvez éliminer l'opérateur Not lorsque vous vérifiez si deux instances d'objet sont différentes :
If MyObj1 IsNot MyObj2 Then
Bien qu'il s'agisse là d'une modification simple, l'opérateur IsNot comble un manque de cohérence dans le langage Visual Basic, rendant ainsi votre code plus clair.
Instruction TryCast
Dans Visual Basic 2003, vous disposez de deux possibilités pour convertir un type d'objet dans un autre :
Dim p As Product
p = CType(obj, Product)
p = DirectCast(obj, Product)
Ici, vous utilisez CType pour convertir un type en un autre, tandis que DirectCast nécessite qu'il y ait une relation d'héritage ou d'implémentation entre les objets. Le problème est que, dans le deux cas, vous obtenez une exception d'exécution si obj ne peut pas être converti dans le type Product.
Entrez la nouvelle instruction TryCast. Vous pouvez l'utiliser comme CType ou DirectCast, sauf que le résultat renvoyé est Nothing si la conversion est impossible à réaliser :
p = TryCast(obj, Product)
If p IsNot Nothing Then
'use the p object...
End If
Surcharge des opérateurs et opérateurs de conversion
Un des ajouts les plus performants dans Visual Basic 2005 est la surcharge des opérateurs. Elle permet de définir des opérateurs qui agissent sur n'importe quel type de votre choix, et vous pouvez même créer vos propres types de base.
L'exemple courant de surcharge d'opérateurs est l'ajout de nombres complexes. Une classe Complex simplifiée avec l'opérateur + surchargé peut se présenter comme ceci :
Public Class Complex
Public Real As Double
Public Imag As Double
Public Sub New(ByVal realPart As Double, ByVal imagPart As Double)
Real = realPart
Imag = imagPart
End Sub
Shared Operator +(ByVal lhs As Complex, ByVal rhs As Complex) _
As Complex
Return New Complex(lhs.Real + rhs.Real, lhs.Imag + rhs.Imag)
End Operator
End Class
Utilisez l'opérateur + pour additionner des nombres complexes de manière tout à fait intuitive :
Dim lhs As Complex = New Complex(2.0, 2.5)
Dim rhs As Complex = New Complex(3.0, 3.5)
Dim res As Complex = lhs + rhs
'res.real = 5.0, res.imag = 6.0
Vous pouvez également surcharger des opérateurs de conversion pour vos types personnalisés. Si vous essayez de convertir la valeur res en CType(res,String), vous obtenez une erreur du compilateur indiquant que Complex ne peut pas être converti en String. Si vous voulez examiner la valeur de Res.ToString, vous obtenez en retour une valeur Complex puisque ToString affiche par défaut le nom de type. Pour résoudre ces problèmes, surchargez l'opérateur de conversion CType et la méthode ToString, comme suit :
Public Shared Narrowing Operator CType(ByVal Value As Complex) _
As String
Return Value.Real.ToString & "i" & Value.Imag.ToString
End Operator
Public Overrides Function ToString(ByVal Value As Complex) As String
Return Value.Real.ToString & "i" & Value.Imag.ToString
End Function
À présent, les valeurs renvoyées pour CType(res,String) et de res.ToString sont telles que vous les attendiez : « 5.0i6.0 ». Les opérateurs de conversion doivent être déclarés avec un attribut de restriction (narrowing) ou d'élargissement (widening) indiquant la manière dont la conversion doit avoir lieu.
Accessibilité des mécanismes d'accès aux propriétés
Un aspect qui m'a toujours préoccupé à propos des propriétés Visual Basic .NET est que les accesseurs Get et Set doivent avoir la même accessibilité (Public, Friend ou Private). Si vous voulez créer une propriété publique en lecture seule (seul Get est public), il n'existe pas d'accesseur Set utilisable dans votre composant pour appliquer une validation ou un traitement personnalisé de la propriété.
Dans Visual Basic 2005, les accesseurs Get et Set peuvent à présent avoir des paramètres d'accessibilité différents, dès l'instant que Set est plus restrictif que Get :
Private _myProp As String
Public Property MyProp() As String
Get
Return _myProp
End Get
Friend Set(ByVal value As String)
If value.Trim.Length > 0 Then
_myProp = value.Trim
Else
value = "<no value>"
End If
End Set
End Property
Ceci s'avère particulièrement utile dans les environnements de développement en équipe ainsi que pour des développeurs individuels désireux de réutiliser leur code au maximum.
Accesseurs aux événements personnalisés
Les accesseurs aux événements vous permettent de définir un événement personnalisé et de contrôler ce qui se produit lorsque des clients ajoutent ou suppriment des gestionnaires et déclenchent l'événement en question. Supposons une classe personnalisée dans laquelle vous déclenchez un événement RateChanged. Vous avez deux possibilités pour déclarer des événements normaux :
Public Event RateChanged()
'or
Public Event HoursChanged As EventHandler
Les événements déclarés de cette façon disposent d'une sauvegarde gérée automatiquement. En d'autres termes, le système contrôle la manière dont l'événement est géré et distribué. Généralement, le mécanisme fonctionne bien, mais parfois, vous avez besoin de mieux contrôler la façon dont s'effectue la notification aux programmes d'écoute de l'événement.
Vous déclarez un événement personnalisé et ses accesseurs à l'aide du nouveau mot-clé Custom. Lorsque vous actionnez la touche Entrée dans la déclaration d'événement, Visual Basic 2005 créé le prototype de code de la même manière qu'il génère les accesseurs Property :
Public Custom Event NameChanged As EventHandler
AddHandler(ByVal value As EventHandler)
'hook handler to backing store
End AddHandler
RemoveHandler(ByVal value As EventHandler)
'remove handler from backing store
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
'invoke listeners
End RaiseEvent
End Event
Lorsque le client ajoute ou supprime un gestionnaire relatif à votre événement, la routine AddHandler ou RemoveHandler s'exécute. Lorsque l'événement est déclenché, la routine RaiseEvent s'exécute. De cette manière, vous pouvez décider d'actions spécifiques en fonction de la façon dont vous voulez gérer le support de sauvegarde de l'événement. Lorsque vous adoptez cette démarche pour créer des événements personnalisés, imaginez que ce sont des propriétés.
Ce mode d'action s'avère utile par exemple lorsque votre objet est sérialisable et que vous avez un événement géré par un objet délégué non sérialisable. Si vous essayez de sérialiser votre objet avec un événement normal, la sérialisation échoue car le support de stockage de l'événement n'est pas sérialisable. Rocky Lhotka (autre MVP Visual Basic) propose une explication du fonctionnement mis en œuvre ainsi qu'un exemple détaillé dans son « blog », accessible à l'adresse http://www.lhotka.net/WeBlog/CommentView.aspx?guid=776f44e8-aaec-4845-b649-e0d840e6de2c
.
Types partiels
Les types partiels permettent la définition d'un type unique dans plusieurs fichiers source. La définition du type a une déclaration normale dans un fichier :
Public Class TestPartial
'implementation...
End Class
Dans d'autres fichiers source, utilisez le mot-clé Partial pour indiquer au compilateur que ce code est la suite de la définition de classe d'origine :
Partial Public Class TestPartial
'implementation...
End Class
Le code des classes générées par des concepteurs dans l'IDE est marqué à l'aide du mot-clé Partial et séparé du code utilisateur. Ajoutez un formulaire nommé TestForm dans un projet et examinez le fichier source résultant : vous risquez d'être surpris en constatant qu'il est vide, à l'exception de la déclaration de classe du formulaire. Où est donc passé tout le code généré par le concepteur, habituellement placé dans la partie Code généré par le Concepteur Windows Form ?
Il se trouve maintenant dans le fichier TestForm.designer.vb, que vous pouvez voir en cliquant sur le bouton Afficher tous les fichiers de la barre d'outils de l'Explorateur de solutions. Vous ne devez pas modifier le code dans ce fichier, mais vous pouvez en copier et en coller des parties dans le fichier TestForm.vb afin de garder certaines informations après la régénération du fichier du Concepteur.
Dans des équipes de projet, l'existence de classes partielles permet de donner à chaque développeur un fichier contenant la partie de la classe le concernant. Grâce à cette possibilité de fractionner une définition de classe en plusieurs fichiers source, les différents développeurs qui travaillent sur les mêmes fichiers source n'ont plus besoin de s'en partager l'accès.
Événements de niveau application
Une autre fonctionnalité nouvelle que vous allez sûrement apprécier est le nouvel ensemble d'événements de niveau application disponible dans une classe partielle nommée MyApplication. Dans l'Explorateur de solutions, cherchez un fichier nommé MyEvents.vb, sous l'élément My Project. Vous trouverez également ce fichier en cliquant sur le bouton View Code de l'onglet Application dans le concepteur d'applications.
Ces nouveaux éléments de niveau application sont semblables à ceux du fichier global.asax dans une application APS.NET. Cinq événements sont exposés :
Les trois premiers sont déclenchés lorsque l'application démarre et s'arrête. NetworkAvailabilityChanged se déclenche lorsque l'état du réseau change sur la machine. Écrivez du code dans l'événement UnhandledException au cas où une exception que vous ne gérez nulle part ailleurs serait générée.
Types non signés
Les trois premiers sont déclenchés lorsque l'application démarre et s'arrête. NetworkAvailabilityChanged se déclenche lorsque l'état du réseau change sur la machine. Écrivez du code dans l'événement UnhandledException au cas où une exception que vous ne gérez nulle part ailleurs serait générée.
-
SByte
-
UShort
-
UInteger
-
ULong
Les types non signés fonctionnent comme des types normaux, à cette différence près qu'ils ne peuvent stocker que des entiers positifs.
Ils sont particulièrement utiles dans Visual Basic pour effectuer des appels à l'API Win32 qui acceptent des types non signés comme paramètres. Le code suivant est un exemple d'appel MessageBox à l'API :
Public Enum WindowsMessageResult As UInteger
OK = 1
Cancel = 8
End Enum
Private Const MB_OK As UInteger = 0
Private Const MB_ICONEXCLAMATION As UInteger = &H30
Private Const MB_OPTIONS As UInteger = MB_OK Or MB_ICONEXCLAMATION
Private Declare Auto Function Win_MB Lib _
"user32.dll" Alias "MessageBox" _
(ByVal hWnd As Integer, ByVal lpText As String, _
ByVal lpCaption As String, ByVal uType As UInteger) _
As UInteger
Public Function MessageThroughWindows(ByVal message As String, _
ByVal caption As String) As WindowsMessageResult
Dim r As UInteger = Win_MB(0, message, caption, MB_OPTIONS)
Return CType(r, WindowsMessageResult)
End Function
Notez que le dernier paramètre et le type renvoyé dans la déclaration Win_MB sont tous les deux des types UInteger.
Les types non signés aident également à préserver la mémoire si vous devez stocker des valeurs supérieures à un Integer. Le type Integer utilise quatre octets de mémoire et peut stocker des valeurs positives et négatives jusqu'à 2 147 483 648. Le type UInteger utilise également quatre octets de mémoire et peut stocker une valeur comprise entre zéro et 4 294 967 295. Sans type non signé, vous auriez besoin d'utiliser un type Long exigeant huit octets de mémoire pour stocker des valeurs aussi grandes.
Instances par défaut
Une autre modification de Visual Basic .NET qui a déstabilisé bon nombre de développeurs venant de Visual Basic 6.0 est l'absence d'instance par défaut pour les formulaires. Vous devez donc créer une instance du formulaire avant de pouvoir l'utiliser :
Dim frm As New Form2
frm.Show()
Aujourd'hui, Visual Basic 2005 gère des instances par défaut de formulaire et vous pouvez donc utiliser la syntaxe familière :
Form2.Show()
Il est préférable toutefois d'accéder à cette instance depuis la collection My.Forms :
My.Forms.Form2.Show()
Avertissements du compilateur
Visual Basic prend en charge des avertissements du compilateur, qui vous donnent une vision directe de ce qui peut poser un problème lors de l'exécution. Un avertissement s'affiche en vert sous votre code (les erreurs sont en bleu).
Les avertissements du compilateur portent notamment sur l'accès récursif à des propriétés, le chevauchement de blocs catch ou d'instructions case, la création d'une fonction sans valeur de retour, etc. Mon avertissement préféré concerne une référence à une variable sur un objet non initialisé :
Dim cust As Customer
If cust.Name.Length = 0 Then
'...
End If
Ici, le compilateur insère une ligne en vert sous la partie cust de l'instruction If. Le texte de l'avertissement affiché indique « variable 'cust' is used before it has been assigned a value » (la variable 'cust' est utilisée alors qu'aucune valeur ne lui a été affectée). Au moment de l'exécution, vous pouviez obtenir une exception de type référence nulle. Je ne sais pas combien de fois j'ai rencontré ce type d'erreur dans mon code au moment de l'exécution, mais à présent, le compilateur le détecte durant la compilation.
Soit dit en passant, lorsque vous tapez le code ci-dessus dans l'éditeur, le compilateur insère initialement une ligne d'avertissement en vert sous cust dans l'instruction Dim avec le message « unused local variable 'cust'» (variable locale 'cust' non utilisée). Cela peut sembler gênant à première vue car vous venez juste d'ajouter la variable, mais en fin de compte, cette mention vous aide à préserver la clarté de votre code.
Au lieu que toutes les erreurs s'affichent dans la Liste des tâches de l'IDE, il existe maintenant une fenêtre Liste d'erreurs qui distinguent trois catégories de messages : erreurs, avertissements et messages (voir les figures 2 et 6). Vous pouvez contrôler si le compilateur repère les avertissements ou les erreurs dans l'onglet Compile du concepteur d'applications, qui contient des cases à cocher permettant soit de désactiver tous les avertissements, soit de traiter tous les avertissements comme des erreurs.
Utilisez l'instruction Option Strict On pour générer les erreurs de compilation selon différents scénarios. Option Strict marque votre code si vous tentez une conversion restrictive implicite (conversion avec perte de données) :
Dim iValue As Integer
Dim lValue As Long
iValue = lValue 'narrowing conversion error
lValue = iValue 'ok
Vous obtenez également une erreur si vous utilisez des liaisons tardives. Une objet est à liaison tardive lorsqu'il est affecté à une variable du type Object :
Dim myObj As Object
Call myObj.method1() 'late binding error
L'utilisation de Option Strict est à présent jugée préférable lors de la programmation avec Visual Studio. Autant que possible, activez Option Strict dans votre code. Vous pouvez activer Option Strict dans le menu Tools | Options, sous les paramètres Project, en cochant la case Option Strict. Vous pouvez également placer l'instruction Option Strict On en haut d'un fichier de module ou de classe individuel.
Limites de tableau explicites
Vous pouvez maintenant déclarer des tableaux en utilisant des limites explicites pour rendre la déclaration plus claire :
Dim a(10) As Integer 'old way
Dim b(0 To 10) As Integer 'new way
Les limites de tableau dans Visual Basic sont encore basées sur zéro ; par conséquent, vous obtenez une erreur du compilateur si les limites inférieures ne sont pas égales à 0.
Conclusion
Le langage Visual Basic 2005 s'enrichit de plusieurs fonctionnalités essentielles et de nombreuses améliorations qui, ensemble, facilitent considérablement son utilisation et augmentent la productivité des développeurs. Le langage est aujourd'hui plus complet et il offre beaucoup plus de points communs avec le langage C# sur des fonctions importantes, telles que les commentaires XML ou la surcharge des opérateurs.
Enrichi d'une multitude d'améliorations IDE, Visual Basic 2005 est en passe de devenir la meilleure version de Visual Basic jamais proposée. Meilleure non seulement en terme de langage, mais aussi quant au plaisir d'utilisation. Je suis simplement déçu de ne pas pouvoir encore créer d'applications de production avec la pré-version Visual Basic 2005. Essayez la version bêta et vous serez certainement d'accord avec moi.