Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

PASSAGE PAR RÉFÉRENCE ET PAR VALEUR


Information sur le tutorial

Catégorie :.NET Tutorial .NET ( DotNet ) Date de création : 20/04/2007 13:33:07 Vu : 6 456 fois

Note :
Aucune note

Commentaire sur cette source (4)
Ajouter un commentaire et/ou une note


Description

Petit tutorial assez simple qui montre la différence entre le passage de paramètre par valeur et par référence via des exemples graphiques.

Tutorial

Passage de variables par référence et par valeur en C#

Note : Ce tutorial explique la différence entre le passage par valeur et le passage par référence en C#.

Petite Intro
Pour savoir si ce tutorial peut vous apprendre quelque chose de nouveau, répondez aux questions suivantes :


Soit le programme suivant :



  • En C#, par défaut, est-ce qu’une variable est passée en paramètre d’une fonction par valeur ou par référence ?


Exemple : Lors de l’appel de la méthode Test2 ci-dessus, t1 est-il passé par valeur ou par référence ?


Réponse
Par défaut, le passage se fait par valeur. Dans l’exemple de la méthode Test2, t1 est une référence sur t qui est passée par valeur.

  • Que vaut la variable i après exécution de la méthode Test1 ?

Réponse
i vaut 5

  • Que vaut la variable t après exécution de la méthode Test2 ?


Réponse
t n’a pas changé, sa variable str vaut toujours init

  • Que vaut la variable i après exécution de la méthode Test3 ?


Réponse
i vaut 15

  • Que vaut la variable t après exécution de la méthode Test4 ?


Réponse
t est réinstancié, str est null

  • Si Test était une structure et pas une classes, aurait-on les mêmes résultats ?


Réponse
Dans ce cas précis, oui.


Si vous n’avez pas tout fait juste, ce tutorial pourra peut-être vous être utile !

Explications

Des schémas valent sûrement bien mieux qu’un long discours. Voyons dans chacun des cas ce qui se passe sur le Stack et sur le Heap pour comprendre le fonctionnement du programme.

Dans les exemples qui suivent, le Stack sera toujours dessiné en rouge, alors que le Heap sera lui en bleu.


Premier exemple, exécution de Test1
On commence par mettre i sur le Stack car c’est une valeur
int i = 5 ;


On appelle maintenant la méthode Test1. x est crée sur le Stack, car c’est une valeur passée par valeur. Elle prend la valeur 5 car c’est la valeur qu’on lui passe en paramètre.
Ensuite, on lui affecte la valeur 4.

La méthode retourne, x meurent (GC) car elle était locale à Test1. Après le retour de la méthode, i reste donc inchangé.


Deuxième exemple, exécution de Test2
On commence par mettre une référence de t sur le Stack. Cette référence pointe sur l’objet qui est lui sur le Heap.
Test t = new Test() ;


On appel maintenant la méthode Test2. t1 est une référence passée par valeur, elle est donc mise sur le Stack et pointe au même endroit sur le Heap que t.

On demande ensuite de créer une nouvelle référence de l’objet t1.
t1 = new Test() ;


La méthode retourne, t1 meurent (GC) car elle était locale à Test2. Après le retour de la méthode, t reste donc inchangé.

Troisième exemple, exécution de Test3

On commence par mettre i sur le Stack car c’est une valeur
int i = 5 ;



On appelle maintenant la méthode Test3. x est crée sur le Stack, c’est une référence qui pointe sur i car c’est une valeur passée par référence. x pointe donc sur la valeur 5.
On affecte ensuite à x la valeur 15. Puisque x pointe sur i, i = 15.




La méthode retourne, x meurent (GC) car elle était locale à Test3. Après le retour de la méthode, i vaut donc maintenant 15.


Quatrième et dernier exemple, exécution de Test4

On commence par mettre une référence de t sur le Stack. Cette référence pointe sur l’objet qui est lui sur le Heap.
Test t = new Test() ;


On appel maintenant la méthode Test4. t2 est une référence passée par référence, elle est donc mise sur le Stack et pointe sur t


On demande ensuite de créer une nouvelle référence de l’objet t2.
t2 = new Test() ;

Puisqu’il pointe sur t, on obtient le schéma suivant :

La méthode retourne, t2 meurent (GC) car elle était locale à Test4. Après le retour de la méthode, t a donc été réinitialisé et sa variable str est null.


Voilà, j’espère que ces quelques schémas ont pu éclairer certaines lanternes ^^

signaler à un administrateur
Commentaire de ecosmose le 27/01/2008 20:07:54

Bien joué ...avec le garbage collector et la casi disparition de la syntaxe * et & dans le langague C# il est bon de rappeler ces quelques mécanismes ...

signaler à un administrateur
Commentaire de billou_13 le 17/10/2008 10:07:07

Chapeau,

L'explication était nécessaire pour éclaircir les idées et ce qui se passe derrière.

Cependant, je me pose la question de l'équivalent C++ du code et je dirais:
public void Test1(int x) => prg->Test1(i)
public void Test2(Test* t1) => prg->Test2(t) //en considérant que Test* t = new Test();
public void Test3(int* x1) => prg->Test3(&i)
public void Test4(Test** t2) => prg->Test4(&t)

Qu'en pensez-vous ?

Bonne journée,


Billou_13

signaler à un administrateur
Commentaire de komard le 20/05/2009 14:40:03

juste une remarque. En C# (et d'autres langages comme Java par exemple) tous les types non primitif sont passés par référence par défaut

ce que tu fais dans la méthode Test2(Test t) est simplement affecter une nouvelle instance (donc créer une nouvelle référence, un nouveau "pointeur"). c'est pour cela que la valeur de t n'a pas changé

au retour de la méthode suivante:
public TestRef(Test t)
{
t.str = "newStr";
}

la valeur de t.str aura changé alors que le mot REF n'est pas utilisé

-------------------------------------------------
class Program
{
    static void Main(string[] args)
    {
        new Program();
    }

    private Program()
    {
        Test t = new Test();
        t.str = "ref";
        Console.WriteLine("Before: {0}", t.str);
        this.TestRef(t);
        Console.WriteLine("After: {0}", t.str);
        Console.WriteLine("Press enter to exit ...");
        Console.ReadLine();
    }

    private void TestRef(Test t)
    {
        t.str = "new ref";
    }

    private class Test
    {
        internal string str;
    }
}
-------------------------------------------------

David

signaler à un administrateur
Commentaire de Bidou le 20/05/2009 21:55:11 administrateur CS

Malheureusement ce que tu racontes est faux :(
Le passage de paramètre se fait par défaut, en C# et en Java, par valeur.


Je peux que t'encourager à relire le tuto. Voici encore quelques liens annexes peut-être utile:

http://msdn.microsoft.com/fr-fr/library/9t0za5es(VS.80).aspx
http://msdn.microsoft.com/fr-fr/library/s6938f28(VS.80).aspx

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,094 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.