Le blog du développement
Les types par référence ou par valeur
Utilisation
Au niveau de l’utilisation standard, ces deux types sont strictement identiques. Dans les 2 cas, on peut faire
maVariable = maValeur; Console.WriteLine(maVariable.ToString());
Explication plus précise
Une variable par valeur contient directement un objet. Au contraire, une variable par référence contient une référence vers cet objet. Pour ceux qui connaissent des langages bas niveau, ça correspond aux pointeurs (à la différence près qu’il n’est pas possible de faire d’opération sur les références comme sur les pointeurs, et que la syntaxe de l’utilisation est identique à celle des variables par valeur).
Les paramètres des méthodes
Lorsqu’on insère un objet en tant que paramètre d’une méthode, on en fait une copie. Ce qui veut donc dire que si l’on modifie une variable dans une méthode, on modifie la copie, et non l’original.
Cependant, si, au lieu de faire une copie de l’objet, on fait une copie de la référence, c’est l’objet original que l’on modifie dans une méthode.
Reconnaître l’un de l’autre
On accède toujours à une classe par référence, et à une structure par valeur.
Structures souvent utilisées : int, short, long, double, decimal, float, char, bool, byte, DateTime, Color…
Classes souvent utilisées : string, Form, List, SqlConnection…
Une autre petite différence, une classe peut avoir la valeur null, contrairement à une structure
La mémoire
La gestion mémoire est totalement différente entre les 2.
Dès qu’une structure est déclarée, sa mémoire est allouée. Et la mémoire est vidée à la fin du bloc dans lequel la variable a été déclarée.
public void maMethode1() { int a; // La mémoire est automatiquement allouée } public void maMethode2() { // Bloc 1 int a; { // Bloc 2 int b; } // Fermeture du bloc 2 // la variable b n'existe plus puisqu'elle a été déclarée dans le bloc 2, et que celui-ci est fermé. } // Fermeture du bloc 1
Concernant les classes, la mémoire n’est allouée que lors de l’utilisation de l’instruction new QuelqueChose() (sauf pour les string). Celle-ci est libérée automatiquement par le GarbageCollector lorsque le programme ne possède plus aucune référence à cet objet, c’est à dire, quand vous n’avez gardé aucun moyen d’y accéder.
public void maMethode() { maClasse a; // mémoire non allouée a = new maClasse(); // allocation de la mémoire a = null; // on perd la référence à l'objet créé ci-dessus. // Il peut être supprimé à tout moment. new maClasse2(); // On crée un objet, mais on ne garde aucune référence à celui-ci. // Il peut donc être supprimé à tout moment par le GarbageCollector }
Le mot clé « ref »
Si l’on souhaite modifier une structure dans une autre méthode, il existe le mot-clé ref. Il suffit d’insérer ce mot-clé avant le type de l’argument dans le prototype de la méthode et de l’indiquer aussi avant la variable dans l’appel à la méthode :
public void maMethode1(ref int maVariable) { maVariable = 10; } public void maMehtode2() { int maVariable = 50; maMethode1(ref maVariable); }
Résumé
struct maStructure { int valeur; } class maClasse { int valeur; } class Program { public static void main() { maStructure s1; // Mémoire allouée maStructure s2; // Mémoire allouée maClasse c1; // Mémoire non allouée maClasse c2; // Mémoire non allouée c1 = new maClasse(); // Mémoire allouée s1.valeur = 10; s2.valeur = 10; c1.valeur = 20; // c2.valeur = 20; va générer une exception puisque c2 ne référence rien c2 = new maClasse(); c2.valeur = 20; if(s1 == s2) Console.WriteLine("s1 et s2 ont la même valeur"); else Console.WriteLine("s1 et s2 ont des valeurs différentes"); // Affichera s1 et s2 ont la même valeur if(c1 == c2) Console.WriteLine("c1 et c2 référencent le même objet"); else Console.WriteLine("c1 et c2 référencent des objets différents"); // Affichera c1 et c2 référencent des objets différents s2 = s1; // On copie la valeur de s1 dans s2 c2 = c1; // On copie la référence de c1 dans c2 // On n'a pas gardé de référence vers l'objet anciennement référencé par c2 // Il peut donc être supprimé à tout moment if(c1 == c2) Console.WriteLine("c1 et c2 référencent le même objet"); else Console.WriteLine("c1 et c2 référencent des objets différents"); // Affichera c1 et c2 référencent le même objet s1.valeur = 1; s2.valeur = 2; c1.valeur = 3; c2.valeur = 4; // Ceci modifie aussi c1, puisque c'est une référence vers le même objet Console.WriteLine(s1.valeur); // 1 Console.WriteLine(s2.valeur); // 2 Console.WriteLine(c1.valeur); // 4 Console.WriteLine(c2.valeur); // 4 } }
Cette entrée a été posté par krimog le 4 mai 2011 à 14 h 41 min, et placée dans Tutoriels de base. Vous pouvez suivre les réponses à cette entrée via RSS 2.0. Vous pouvez laisser une réponse, ou bien un trackback depuis votre site. |