Cours de visual basic .net 2005: des points obscurs expliqués

Visual Basic .net 2005 : des points obscurs expliqués

GÉNÉRALITÉS

Ceci n'est pas un cours classique. Je veux dire que vous ne trouverez pas ici un cours qui vous apprendra visual basic .net du début à la fin. Ce cours s'adresse à des gens qui connaisse déjà ce langage, ou à des gens qui sont en train de l'apprendre sur un autre cours. Mon ambition est juste d'éclaircir certains points de visual basic .net qui ne sont pas précisés ailleurs, et qui sont très utiles pour comprendre véritablement VB. En apprenant moi-même Visual Basic, à certains moments il m'était difficile d'assimiler certaines choses à cause d'un manque d'explications données sur, par exemple, la façon dont se passent les choses réellement. Ce cours est donc un fourre-tout, où vous trouverez des précisions sur un peu tous les sujets de visual basic. A vous donc d'y chercher ce dont vous avez besoin. Je le complèterai petit à petit.

La classe "form1"; le formulaire principal

Lorsque vous créez une Windows application dans visual studio 2005, visual studio vous crée par défaut une classe qu'il appelle (par défaut) form1. Vous vous retrouvez donc avec un code de cette classe form1.

Cependant, une question intéressante est de s'étonner qu'une simple classe va créer et afficher un formulaire Windows! Car en fait, créer une classe, c'est juste une déclaration d'une classe, et c'est tout. Cela ne fait pas plus que cela. J'imagine que beaucoup de débutants pensent que c'est ce code de la classe form1 qui, exécuté, va afficher le formulaire Windows! Et bien non, ce n'est pas cela. Le code de la classe form1 sert uniquement à définir une classe, comme n'importe quelle définition de classe.

Visual studio va, en réalité, ajouter du code supplémentaire qui va, d'abord, créer un objet de cette classe ; donc un objet formulaire. Puis il va afficher cet objet. Il ajoute donc l'équivalent des lignes suivantes (ce code n'est pas situé à l'intérieur de la classe form1, mais dans le programme principal) :

Dim formu as new form1
show( )

Et voilà, voici l'explication de comment cela se fait qu'un formulaire s'affiche quand on exécute l'application!

Comment récupérer l'objet formulaire

Il existe un problème: on ne connaît pas le nom de cet objet formulaire, que VB crée de manière transparente! Il se peut qu'il l'appelle aussi "form1", car la propriété "name" de la classe form1, contient "form1". Mais cela ne nous avance pas beaucoup, car quand on tape "form1" dans l'éditeur (EDI), visual croit qu'on parle de la classe form1. Donc aucun moyen (à ma connaissance) d'accéder aux membres d'instance (c'est-à-dire aux membres non shared) de l'objet formulaire, en dehors de la classe form1. Car dans la classe form1, on peut accéder aux membres d'instance car on se trouve dans la classe de l'objet formulaire.

La solution que j'ai trouvé est de déclarer une variable globale dans un module standard.

Par exemple, dans un module standard module1, on crée une variable globale appelée "formu_pr" (formulaire principal). On crée le module standard avec add new item, et en choisissant module.

Puis on déclare la variable globale:
Public formu_pr as form1

Ainsi, on déclare une variable globale formu_pr, qui est capable de contenir un objet de la classe form1.
On peut dire aussi que formu_pr est une référence sur un objet de la classe form1. C'est-à-dire que formu_pr contient l'adresse d'un objet de la classe form1. Cette variable contiendra l'adresse du formulaire principal.

Ensuite, il suffit d'ajouter dans le form1_load: formu_pr = me .
Ainsi, dès le démarrage du programme, la variable formu_pr sera initialisée avec l'objet formulaire principal. Car, à l'exécution, visual va d'abord créer un objet formulaire (code caché) :
dim formu as new form1.

Puis il va faire (code caché) :
formu.show( )

Le formu.show va exécuter d'abord formu.load (avant d'afficher le formulaire à l'écran). Donc il va initialiser notre variable globale : formu_pr = formu (car me=formu, ici). Donc formu_pr contiendra bien, dès l'exécution du programme, l'objet formulaire principal!

Désormais, dans toute notre application, on pourra utiliser formu_pr comme bon nous semblera, afin d'accéder aux membres non partagés (non shared) du formulaire principal, en dehors de la classe form1. Simplement en faisant formu_pr.propriété (par exemple formu_pr. size), ou formu_pr.méthode (par exemple formu_pr.activate( )). Sans notre variable formu_pr, il nous aurait été impossible d'accéder à la propriété size du formulaire, ou à sa méthode activate( en dehors de la classe form1).

Des objets créés par visual studio

Il existe un point intéressant à souligner. Certaines méthodes de visual basic .net créent des objets elles-mêmes. Puis elles nous renvoient la référence de cet objet créé (afin qu'on puisse en profiter, par exemple le lire). Donc, dans ce cas, il n'y a pas de new à faire! Car c'est visual basic qui va faire ce new. Je suppose que le débutant ne sait jamais quand il doit faire un new ou pas. En comprenant ceci, cela l'aidera beaucoup. C'est en comprenant cela qu'on sait alors s'il faut faire le new (donc la création d'objet) ou pas.

Prenons un exemple: la fonction shared system.enum.getvalues .
L'info bulle jaune de l'environnement de visual studio nous indique: Public Shared Function GetValues(enumType As System.Type) As System.Array .
C'est donc une méthode de la classe enum. Cette méthode est partagée, c'est à dire qu'elle est accessible sans avoir d'objet, en faisant system.enum.GetValues . Cette fontion sert à donner, pour une certaine énumération, toutes les valeurs possibles de cette énumération.
Par exemple, une énumération EtatVoiture
Enum EtatVoiture
ARRET
DEMARRE
ROULE
FREINE
End Enum

Puis, à un autre endroit:
Dim etat as EtatVoiture

Lorsqu'on va faire :

Dim tab as system.array
tab = system.enum.GetValues( etat.GetType( ) )
console.writeline( tab(0).tostring( ) )

Ceci va afficher "ARRET" dans la console.
tab(0) est de type EtatVoiture. Donc en faisant tab(0).tostring( ), on applique la méthode tostring() particulière à la classe enum. Tab(0).tostring( ) vaut dont une string "ARRET".

Ce qui est à retenir de cet exemple, c'est que le programmeur n'a pas dû créer le tableau tab avec un new. Il a juste créé une variable référence, qui contient l'adresse du tableau en mémoire. Il n'a pas fait de new dans Dim tab as system.array.
On remarque donc que c'est la méthode GetValues qui a créé un objet de la classe system.array . Elle a donc fait le new elle-même!

Il est important de prendre conscience qu'il arrive que certaines fonctions ou procédures de visual basic créent des objets toutes seules. Ce qui peut paraître un peu étrange. Il ne faut donc pas faire de new dans ce cas.

Les variables qui contiennent des références

Prenons l'exemple suivant:

Dim voit as new voiture

Bien sûr, on peut affirmer que "voit" est un objet voiture, qui a été créé avec new (par exemple à l'adresse 10000, adresse purement fantaisiste).
Mais "voit" est aussi une variable locale qui est créée, et qui a été initialisée avec la référence à l'objet voiture, c'est à dire l'adresse de l'objet voiture, soit 10000.
Donc, sous le nom "voit", il y a deux choses distinctes
- "voit" est l'objet de la classe voiture, situé à l'adresse 10000
- "voit" est une variable locale, qui est créée par visual basic, et à laquelle il affecte le nombre 10000.

Selon le contexte, on parle soit de l'un, soit de l'autre. Mais il faut bien comprendre que "voit" peut désigner deux choses distinctes. Le programmeur, notamment débutant, n'a pas toujours conscience de cela. Et il ne distingue pas clairement, dans son esprit, ces deux éléments. Souvent, il ne pense qu'à la voiture "voit" elle-même, sans avoir compris qu'il existe également une variable locale qui a été créée, et à qui on a affecté la référence de l'objet "voit".

Le fonctionnement du garbage collector

Définition générale

Le langage visual basic 2005 .net possède un garbage collector. C'est une technologie qui nous permet de ne pas avoir à libérer (comme en langage C, par exemple) la mémoire qu'on nous a allouée dynamiquement (c'est à dire lors d'un new).
Ce système évite les oublis de libération de mémoire, qui sont un souci constant pour le programmeur C, et qui peuvent être catastrophiques.
De plus, certaines classes, qui sont l'objet d'allocation importante de mémoire, comme la classe image, possèdent une méthode dispose. Cette méthode permet de libérer nous-même la mémoire, sans avoir à attendre le garbage collector. Par conséquent, le système utilisé par visual basic quant à la libération de la mémoire cumule les avantages des deux façons de procéder pour libérer la mémoire.

Fonctionnement détaillé

Cependant, une question se pose, qui me laissait perplexe. D'accord, le garbage collector libère la mémoire dont on n'a plus besoin. Mais comment s'y prend t-il pour savoir qu'on n'a plus besoin de cette mémoire, étant donné qu'on ne lui demande jamais de la libérer?

Le principe est le suivant. Prenons l'exemple qui suit.

public sub form1_load( ... )
ma_procedure( ) 'Appel de ma_procedure
'Après l'appel, la variable locale 'voit' n'existe plus
'Donc l'objet voit, n'étant plus référencé par aucune
'variable de référence, est détruit par le garbage
'collector
end sub

Public sub ma_procedure( )
Dim voit as new voiture( )

End Sub

Dans la sub ma_procedure, un objet de la classe voiture est créé en mémoire. Puis une variable locale voit est créée, et elle est initialisée avec la référence de l'objet voiture. Dans form1_load, on appelle ma_procedure. Après l'appel, la variable locale voit est détruite (car on quitte la sub qui l'a créée). Et l'objet de la classe voiture n'est alors plus référencé par aucune variable. Et il ne pourra plus être utilisé, si on ne sait pas où il se trouve! Le garbage collector peut alors en déduire que c'est un objet qui n'est plus utilisé, et il peut le détruire.

Conclusion: le garbage collector détruit les objets qui ne sont plus référencés par aucune variable de référence.

Remarque : il est aussi possible de détruire certains objets 'manuellement'. L'avantage est que la libération de la mémoire se fait plus rapidement, dès qu'on le demande. Et on sait aussi quand elle a lieu. Ceci est le cas des objets qui ont une méthode dispose( ). Ainsi, la classe image a une méthode dispose( ), qui, si elle est appelée, libère l'espace mémoire qui était utilisé par l'image. Visual basic a prévu une méthode dispose pour les gros objets, comme les images. La classe system.windows.forms.control (celle dont hérite tous les contrôles) possède une méthode dispose( ) également.

Ce document intitulé « Cours de visual basic .net 2005: des points obscurs expliqués » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous