Site:  Cours VB.net  
1.6.7 Les variables par valeur ou par référence.

Résumons la notion très importante de variable  par valeur ou par référence.

 

Un type de données est un type valeur s'il contient des données dans l'espace qui lui est alloué en mémoire. Un type référence contient un pointeur vers un autre emplacement en mémoire contenant les données.(dixit MicroSoft)

 

La variable 'par Valeur':

Contient réellement une valeur.

Prenons pour exemple une variable de type 'Long'

Dim L As Long

L= 1456

L occupe 8 octets nécessaire pour coder un long, ici L a une valeur de 1456, donc dans ces 8 octets il est codé 1456.

Quels sont les types de variables par 'Valeur'?

Les Integer, les Long les Short

Les Single, Double, Decimal

Les Booleans, Char, Date

Les Structures

Les énumérations

 

La variable 'par Référence':

Elles ne contiennent pas la valeur de l'objet mais son adresse en mémoire, sa référence.

Dim O As Object

O contient l'adresse de l'objet codée sur 4 octets.

Quels sont les types de variables par référence:

Les Objets

Les Strings

Les tableaux

Les Classes

 

Influence sur l'Affectation:

Posons le problème:

Travaillons sur A et B, 2 variables ayant la même 'nature'.

Dim A As ...

A existe donc, faisons:

Dim B=A

Puis modifions la valeur de A, cela modifie t-il B? 

Les variables par Valeur ou par Référence ne réagissent pas de la même manière:

Si le type de variable est par valeur (valable pour les entiers, les Long.. les structures..), chaque variable ayant sa valeur, B n'est pas modifié.

Si le type de variable est par référence  (valable pour les tableaux, les objets, les string..), chaque variable est définie par sa référence (son lieu physique); faire A=B entraîne que A et B ont même référence. Si on modifie A, B est  modifié car il pointe au même endroit.

Voyons des exemples:

Même si on affecte une variable par valeur à une autre, les deux variables restent différentes: elles conservent leur propre espace de stockage:

Dim L As Long

Dim P As Long

L=0

L=P     'on affecte P à L

P=4     'on modifie P

=> L=0 P=4    Modifier P n'a pas modifié L

 

Par contre si on affecte une variable par référence à une autre, elle pointe toutes les 2 sur le même endroit mémoire: si j'en modifie une, cela modifie l'autre.

Créons une Classe contenant un entier (Exemple à relire quand vous aurez étudié les Classes)

Class Class1
   Public Value As Integer = 0
End Class

Dim C1 As New Class1()
Dim C2 As Class1 =
C1    'on crée C2, on affecte C1 à C2
C2.Value = 123         
'on modifie C2
 

=> C1.Value=123  C2.Value=123    Modifier C2 a modifié C1 car elles pointent sur le même endroit mémoire.

 

On se méfiera donc du type 'référence ' ou 'Valeur' des données que l'on utilise: exemple des Tableaux

Exemple sur les tableaux qui sont 'Par référence':

 

Dim A(3) As String

A(1) = "a"

Dim B(3) As String

B(1) = "b"

B = A

A(1) = "c"

Label1.Text() = B(1)    'Affiche 'c'

 

En effet un tableau est 'par référence' et le fait de faire A=B donne la même adresse mémoire aux 2 tableaux, aussi , modifier l'un modifie l'autre.

B= A.Clone aurait copié le tableau A dans B en conservant 2 tableaux distinct et la dernière instruction aurait affiché 'a'.

Remarque: A(2)=B(2) affecte un élément d'un tableau à un élément d'un autre tableau, cela ne modifie que la valeur d'un élément et n'affecte pas le tableau.

 

Le cas particulier des 'String' qui sont 'Par référence':

Attention: par contre :

Dim A As String

A = "a"

Dim B As String

B = "b"

B = A

A = "c"

Label1.Text() = B    'Affiche 'a'

Bien que cela soit par référence, B=A affecte simplement la valeur de A à B, si on modifie ultérieurement A, B n'est pas modifié. (idem pour clone et copy!!) Pour une string qui est 'par référence', il parait donc impossible de la dupliquer, elle se comporte comme une variable par valeur!! Avez -vous des idées pour expliquer cela?

L'opérateur d'affectation "=" de deux strings "A=B" a simplement été
défini de manière restrictive pour les strings. Les créateurs de vb .net
lui ont permis uniquement une copie de la valeur de la string et non de la référence.
Il vaut mieux ne pas  permettre l' affectation de la même référence pointant sur le même
objet c'est dangereux pour les débutants et cela serait totalement incompatible avec les versions précédentes..
Ensuite, parce que la copie de la valeur d'une string dans une autre est
une opération extrêmement courante chez les programmeurs. Ce qui n'est
pas le cas de l'affectation de la même référence pointant sur le même
objet.
En conclusion, rien de choquant dans le fait qu'un type string se comporte
comme un type par valeur: car c'est juste la définition de l'opérateur
d'affectation "=" qui a été redéfinie, et c'est tout. Tout ce qui concerne
l'implémentation du type string est strictement comme tous les types
par référence. (Merci Sabri)
 

 

Déclaration avec New ?

En théorie, il faut utiliser New quand on déclare une variable 'par référence':

Il faut écrire:

Dim L As Long    'un long est 'par valeur'

Dim F As New Button    'un bouton est un objet 'par référence'

En fait

Dim L As New Long  'est accepté

Dim O As Object    'est accepté mais il faudra redéfinir O avec New pour l'utiliser.

Dim S As String    'est accepté.

Pour les Classes ou les objets graphiques , il faut par contre bien taper New pour créer l'objet:

Dim F As New Button

Si on tape  Dim F As Button on crée une référence vide, mais pas d'objet Button.

 

 Valeur après déclaration:

Après création (avant initialisation) une variable numérique 'par Valeur' contient 0,

Dim L As Long    'L contient 0

Par contre une String  (par référence) qui a été créée par Dim et non initialisée contient Nothing.

Dim O As Object    'O contient Nothing: il ne pointe sur aucun objet.

On peut le tester par  If IsNothing( O ) then.. ou If O Is Nothing..

Pour les tableaux, bien que le tableau soit 'par Référence', c'est le type de variable utilisée dans le tableau qui décide de la valeur des éléments après déclaration.

Dim T(3) As Long    '=>T(0)=0

 

Comparaison:

1-Une variable par Valeur peut être comparée à une autre par "=",

Dim L As Long=12

Dim P As Long=24

If L=P Then..

 

2-Par contre une variable par référence peut être comparée à une autre par "Is".

Dim O As Object

Dim Q As Object  

If O Is Q then..

NB: pour les String '=' et 'Is' peuvent être utilisés.

 

3-Equals peut être utilisé pour comparer les 2 types de données:

Obj1.Equals(Obj2))  'Retourne True si Obj1 et Obj2 ont le même pointeur.

ou

N1.Equals(N2)    'Retourne True si la valeur de N1= la valeur de N2
 

Pour les types référence, l'égalité est définie comme une égalité d'objets, c'est-à-dire si les références renvoient ou non au même objet. Pour les types valeur, l'égalité est définie comme une égalité au niveau du bit de la valeur.

 

Il existe une instruction permettant de voir si une variable est de type 'Par référence'

Cet exemple utilise la fonction IsReference (Microsoft.VisualBasic.Information.IsReference)
 pour vérifier si plusieurs variables font référence à des types référence.

Dim R as Boolean

Dim MyArray(3) As Boolean

Dim MyString As String
Dim MyObject As Object
Dim MyNumber As Integer
R = IsReference(MyArray)
'  R= True. Tableau
R = IsReference(MyString) ' R= True. String
R = IsReference(MyObject) ' R= True. Objet
R = IsReference(MyNumber) ' R= False. Entier