Bonjour est-il possible d'avoir une explication simplifiée de ce concept de valeur et de référence car je n'arrive pas à totalement le saisir.
D'avance merci.
Bonjour est-il possible d'avoir une explication simplifiée de ce concept de valeur et de référence car je n'arrive pas à totalement le saisir.
D'avance merci.
Je viens de trouver une bonne explication sur un autre site :
.NET distingue deux types de données différentes :
- les types valeurs (int, float, doube, struct, etc.) stockés sur la pile et passés en paramètres par copie
- les types références (object, string, class, etc.) stockés sur le tas managé et passés obligatoirement en paramètre, par référence
Pour forcer un type valeur à être passer en référence et pouvoir donc le modifier depuis une autre méthode, vous pouvez utiliser les mots clés ref ou out.
out et ref fonctionnent de la même manière, excepté que out permet de passer par référence un paramètre non initialisé
J’ai des questions à toutes vos réponses!
Vu le nombre d'articles techniques sur Internet sur ce sujet, je vais essayer une nouvelle méthode pédagogique pour expliquer le passage par référence et par valeur :
Si je te dis que je gagne 2 500 euros. Tu peux me retourner "ouai il gagne pas trop mal sa vie". Ça, c'est du passage par valeur !
Si maintenant je te donne en billets tout mon salaire de 2 500 euros. Que tu claques la moitié, et que tu me rendes 1 250 euros. Bon j'ai perdu un peu de tunes, il y a eu un peu d'effet de bord et de casse, car c’est du passage par référence !
Heureusement que par défaut, on passe les entiers en valeur, car à force je perdrai pas mal d'argent avec toi !
Le String de ta copine est un bel Objet, il n'est pas primitif mais se comporte comme tel; en effet le sacré vicelard qui a écrit la Framework, l'a rendu immuable (=pas modifiable), pour que le passage du String se fasse par copie! Du coup ta copine est sûr de ne jamais le perdre, ni même qu'il ne rétrécisse en le passant à la machine !
EDIT:
Merci tomlev pour la correction
merci les amis pour vos réponses et spécialement alavoler pour le type de réponse que je recherchais précisément!
même si je n'ai pas totalement saisir l'exemple
mais je pense que le simple est:
le passage par valeur : on passe la valeur, pas l'objet lui même, ce qui fait s' il y'a un changement dans la valeur. l'objet gardera ça valeur initiale.
le passage par référence :on passe l'objet lui même et ,si bien sûr, il a changé ça valeur changera.
un exemple ça sera plus parlant
si on fait :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 void Updatebyval(string valeur) { valeur="azstar;Version par valeur"; } void Updatebyref(ref string valeur) { valeur="azstar;version par ref "; }
j’espère que c'est clair
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 //par valeur string value="Walo"; Updatebyval(value); //ICI la valeur de value restera toujours "Walo" Updatebyref(ref value); //ICI la valeur changera et sera "azstar;version par ref "
Si tu aimes ma Réponse pense à cliquer sur
Visiter mon blogEt mes codes sources
- La simulation de navigation dans internet explorer avec Interop.SHDocVw
- Protéger mes données de configuration dans une dll compilée
D'après ce que j'ai compris les types valeurs c'est leur valeurs stockées tel quel en mémoire avec lequel tu travail, alors que les types par référence c'est un pointeur vers l'objet en mémoire.
Donc quand tu copie un type valeur c'est cette valeur que tu copie à un autre emplacement mémoire, alors que pour le type par référence c'est le pointeur que tu copie résultat ce pointeur pointe toujours au même endroit.
PS: le string à un fonctionnement assez particulier.
bonjour ezrider
Attention au Passage par defaut (sans specification precise dans l'Appelant le Caller):
- les types valeus sont passes par Valeur...
- les types references sont passes Reference...
doc MSDN rubrique
Passage par référence et Passage par valeur:
Sur un plan pratique et terre à terre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 Par défaut, lorsqu'un type valeur est passé à une méthode, une copie est passée plutôt que l'objet lui-même.Par conséquent, les modifications apportées à l'argument n'ont aucun effet sur la copie d'origine dans la méthode d'appel.....(plus loin).... Les types référence sont passés par référence. Lorsqu'un objet d'un type référence est passé à une méthode, la référence pointe vers l'objet d'origine, et non vers une copie.Les modifications apportées par le biais de cette référence seront par conséquent répercutées dans la méthode d'appel
- si tu veux passer un type Valeur (entier,double,boolean ) par Reference utilise la double specification [IN,OUT] ...car c'est un type valeur....
- inversement si tu veux passer un type Reference (class,array ) par Valeur utilise la specification [IN] ...car c'est un type Reference....
bon code.............
C'est un sujet assez délicat, sur lequel même des développeurs expérimentés se mélangent souvent les pinceaux...
Attention de ne pas confondre deux notions qui peuvent sembler similaires mais sont en fait tout à fait différentes et indépendantes :
- la différence entre types valeur et types référence
- la différence entre le passage par valeur et le passage par référence
Cet article explique assez bien ces notions
Non. Il faut arrêter avec ce "mythe" selon lequel string serait un cas particulier ; c'est un type référence, qui fonctionne comme tous les types références. Sa seule particularité, c'est qu'il est immuable (pas modifiable), ce qui fait qu'on peut généralement le traiter de la même façon que les types valeur.
D'autre part il n'y a pas "d'opérateur de copie"... Je suppose que tu fais référence à l'opérateur d'affectation (=), mais il fonctionne pour string comme pour tous les autres types référence...
Non, pas du tout. Par défaut, tous les types sont passés par valeur, y compris les types référence. Tu fais justement la confusion que j'ai mentionnée plus haut...
Pas de questions techniques par MP ! Le forum est là pour ça...
Tutoriels : Les nouveautés de C# 6 - Accès aux données avec Dapper - Extraction de données de pages web à l'aide de HTML Agility Pack - La sérialisation XML avec .NET (Aller plus loin) - Les markup extensions en WPF
bonjour tomlev
Mmh... ce n'est pas moi qui confond...c'est probablement la doc MSDN VS2010 qui fait des siennes .Qu'en penses-tu?
Parce que je fais que la citer (je m'y suis refreree)....
bonne journee......
Salut
-----
La confusion survient surtout lorsqu'on passe un type référence par référence.
Par défaut, comme Tomlev l'a bien expliqué, on passe les types références par valeur. En fait, ça revient à opérer une simple indirection:
Si on a une variable "monobjet" de type référence, monobjet contient le pointeur vers l'objet lui-même (le contenu de l'objet).
Lorsqu'on modifie une propriété de "monobjet", on modifie le contenu de ce qui est pointé par "monobjet": c'est une indirection simple.
Si on modifie "monobjet" lui-même, par exemple avec "monobjet = new...." ou "monobjet = null", etc, alors on modifie le pointeur, et donc sur ce vers quoi il pointe. "monobjet" ne référencie plus le même objet.
Si on passe "monobjet" à une méthode, par exemple, on passe par défaut par valeur, c'est à dire qu'on copie (c'est important) la valeur du pointeur et qu'on passe cette copie à la méthode. Admettons que cette méthode affecte cette copie au nom de variable "monobjet2", genre :
public void method (objetType monobjet2)
{...}
On se retrouve avec la situation suivante:
- monobjet : pointe sur le contenu de l'objet
- monobjet2 : est une copie de monobjet et donc pointe sur le contenu de l'objet
Si maintenant on modifie dans la méthode une propriété de "monobjet2", alors on va modifier l'objet pointé. Vu que cet objet est le même que celui pointé par "monobjet" dans la routine appelante, les modifications seront répercutées sur le contenu pointé par "monobjet" et donc par ce qu'on peut dire sur "monobjet" dans la routine appelante.
MAIS si maintenant, dans la méthode, on affecte une nouvelle valeur à "monobjet2", que se passe-t-il?
en fait, monobjet2 contenait une COPIE de monobjet (une copie du pointeur). Donc, si on écrit : monobjet2 = new objettype()..., on va REMPLACER la valeur de monobjet par une nouvelle.
Or, la valeur de monobjet c'est un pointeur et non le contenu de l'objet, et donc c'est une référence vers le contenu de monobjet. On se retrouve donc avec la situation suivante:
- monobjet pointe sur l'objet "monobjet"
- monobjet2 pointe sur un autre objet
Moralité, en modifiant une propriété de monobjet2 dans la méthode appelée, on ne modifie plus l'objet pointé par monobjet dans la méthode appelante, et donc on travaille sur 2 objets distincts. Les modifications sur monobjet2 ne se répercuteront plus sur monobjet "passé" en paramètre.
Dit autrement, il est impossible avec un passage par valeur de modifier l'objet lui-même, on peut uniquement modifier son contenu.
monobjet2 = null ne rend pas monobjet null
monobjet2 = new objettype() ne modifie pas l'objet pointé par monobjet
Maintenant, si on passe le type référence par référence, que se passe-t-il?
Ben, en réalité on opère une double indirection. En effet, plutôt que de passer une copie du pointeur pointant sur le contenu de monobjet, on passe un pointeur sur le pointeur pointant sur le contenu de monobjet.
Dit autrement:
Par valeur, monobjet et monobjet2 pointent sur le contenu d'un objet
var référence: monobjet2 pointe sur monobjet1 qui pointe sur le contenu d'un objet.
Maintenant, que se passe-til si on modifie une propriété de monobjet2 dans la méthode appelée?
On va en fait récupérer l'adresse de monobjet à partir de monobjet2, puisque monobjet2 pointe sur monobjet alors que dans le cas précédent il pointait directement vers le contenu de l'objet.
Ensuite, on va pointer sur le contenu de monobjet via le pointeur "monobjet".
Et, au final, on va modifier l'objet pointé par monobjet, qui est le même que l'objet pointé par monobjet2.
Moralité, à ce niveau, rien ne change, sauf qu'on opère une double indirection, invisible pour l'utilisateur, pour accéder au contenu de monobjet.
La où ça change, c'est si on se met à modifier l'objet référencé double-indirectement par monobjet2.
En effet, si maintenant on écrit monobjet2 = new objettype(), que se passe-t-il?
En fait, monobjet2 est un pointeur pointant sur monobjet, et donc lorsqu'on va écrire ça, on va créer un nouvel objet donc le pointeur va être retourné non pas à monobjet2, mais à ce qui est pointé par monobjet2. Or, ce qui est pointé par monobjet2, c'est le pointeur monobjet.
Moralité, on récupère le pointeur sur le nouvel objet et on affecte la valeur de ce pointeur à l'objet pointé par monobjet2, et donc à monobjet.
Donc monobjet dans la routine appelante pointe maintenant sur le nouvel objet et plus sur l'ancien. Et vu que monobjet2 pointe sur monobjet qui pointe sur le nouvel objet, monobjet2 référence aussi le même objet.
Passer un type référence par référence est donc l'unique moyen de modifier non seulement le contenu de l'objet pointé, mais également l'objet pointé lui-même, tout simplement parce qu'on opère une double indirection qui est nécessaire dans ce cas particulier.
Le passage par "out" n'est qu'un passage par référence classique, la seule différence est qu'on signale au compilateur chargé de vérifier la syntaxe que l'initialisation de l'objet pointé se fait dans la méthode appelée plutôt que classiquement dans la méthode appelante.
Si maintenant les types références n'étaient pas passés par valeur par défaut, on ne pourrait pas écrire par exemple:
var button = new Button();
.. button.xxx= xxx
.. button.xxx= xxx
this.Add(button)
button = new Button();
.. button.xxx= xxx
this.Add(button)
car la deuxième création d'un bouton, affecté à la même variable, affecterait le bouton déjà ajouté à la fenêtre. Comme le passage est fait par valeur, il s'agit en fait de 2 boutons différents (mais on a perdu la référence sur le premier bouton).
Raisonner avec un type variable est exactement identique mais en plus simple. Au lieu de 1 indirection (passage par valeur) ou 2 (passage par référence) on a respectivement 0 et 1 indirection.
A+
Claude
Je ne retrouve pas ce passage dans la doc MSDN ; pourrais-tu donner le lien ?
En tous cas, il n'y a absolument aucun doute sur le fait que, sauf mention contraire (utilisation du mot-clé ref), les paramètres sont toujours passés par valeur par défaut. C'est valable même pour des types référence : la valeur de la variable est une référence, qui est passée par valeur.
Pas de questions techniques par MP ! Le forum est là pour ça...
Tutoriels : Les nouveautés de C# 6 - Accès aux données avec Dapper - Extraction de données de pages web à l'aide de HTML Agility Pack - La sérialisation XML avec .NET (Aller plus loin) - Les markup extensions en WPF
bonjour à tous
Voici le topic (english) ou j'ai pris la malheureuse citation:
http://www.google.fr/url?q=http://ms...9Qo4hIB0EonyBw
Le paragraphe cite s'intitule :
et le code .cs suivant illustratif:Passing by Reference vs. Passing by Value
By default, when a value type is passed to a method, a copy is passed instead of the object itself.
plus loin ....
When an object of a reference type is passed to a method, a reference to the object is passed. That is, the method receives not the object itself but an argument that indicates the location of the object. If you change a member of the object by using this reference, the change is reflected in the argument in the calling method, even if you pass the object by value.
et ce commentire sybyllin le suit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 public class SampleRefType { public int value; } public static void TestRefType() { SampleRefType rt = new SampleRefType(); rt.value = 44; ModifyObject(rt); Console.WriteLine(rt.value); } static void ModifyObject(SampleRefType obj) { obj.value = 33; }
et ici le meme topic MSDN fr ou j'ai relu pour m'assurer avant de poster :The example does essentially the same thing as the previous example in that it passes an argument by value to a method. But, because a reference type is used, the result is different. The modification that is made in ModifyObject to the value field of the parameter, obj, also changes the value field of the argument, rt, in the TestRefType method. The TestRefType method displays 33 as the output.
http://www.google.fr/url?q=http://ms...B8SSI3Gu38Guyw
bonne soiree........
Avec Reflector tu n'y verras pas grand chose, parce que le type String est en grande partie implémenté directement dans le CLR, donc pas en code managé...
En gros, il est immuable tout simplement parce qu'il n'existe aucun moyen de modifier les caractères qui composent la chaine (*) ; une fois initialisée, une instance de String contiendra toujours la même chaine.
(*) en fait c'est possible, mais en "trichant", avec du code unsafe par exemple... mais bon, quand on commence à faire du unsafe, il n'y a pratiquement plus aucune garantie sur quoi que ce soit...
Je pense que tu as mal interprété ce qui est dit dans cette page... il faut dire que ça prête un peu à confusion.
Ici pas d'ambiguité, il s'agit simplement du passage par valeur d'un type valeurBy default, when a value type is passed to a method, a copy is passed instead of the object itself.
A mon avis c'est cette phrase qui t'a induit en erreur : une référence à l'objet est passée, mais ça ne veut pas dire que l'objet est passé par référence ! Pour une variable de type référence, la valeur de la variable est une référence ; quand tu la passes en paramètre à une méthode (sans le modificateur ref), cette référence est passée par valeur. La méthode reçoit une copie de la référence, et affecter une autre référence au paramètre à l'intérieur de la méthode ne modifiera pas ce que voit l'appelant. Par contre, si la méthode modifie les propriétés de l'objet via le paramètre, ces modifs seront visibles par l'appelant, puisqu'il s'agit toujours du même objetWhen an object of a reference type is passed to a method, a reference to the object is passed.
Voilà une petite analogie un peu bête, mais relativement juste :
- Passage par valeur d'un type référence :
Je promène mon chien en laisse. Je veux que tu puisses aussi promener mon chien. Je te donne donc une autre laisse attachée au collier du même chien. Si tu décides de tondre le chien qui est au bout de la laisse, c'est bien mon chien qui est tondu ; mais si tu détaches la laisse pour l'attacher à un autre chien, ça ne change rien pour moi : j'ai toujours mon chien à moi au bout de ma laisse, et tu ne peux pas changer ça.
- Passage par référence d'un type référence :
Je ne veux pas promener mon chien, je veux que tu le fasses à ma place. Je te donne donc ma laisse attachée à mon chien (la mienne cette fois, pas une autre laisse). A la fin de la promenade, tu me ramènes ma laisse, mais rien ne garantit que c'est toujours mon chien qui est au bout : ça pourrait être un autre chien, ou pas de chien du tout... puisque tu avais la laisse, tu pouvais faire ce que tu voulais avec
(au cas où ça ne serait pas clair : dans cet exemple, le chien est l'objet, les laisses sont les variables, et le fait de tondre le chien est une modification de l'état de l'objet)
Toujours pareil : l'objet est modifié (plus exactement : son état est modifié), mais la variable pointe toujours sur le même objet qu'avant : c'est bien un passage par valeur, pas par référence (même si c'est une référence qui est passée par valeur)
Pas de questions techniques par MP ! Le forum est là pour ça...
Tutoriels : Les nouveautés de C# 6 - Accès aux données avec Dapper - Extraction de données de pages web à l'aide de HTML Agility Pack - La sérialisation XML avec .NET (Aller plus loin) - Les markup extensions en WPF
Pro
J'essaierais de me souvenir de cette histoire de chien et de laisse. C'est assez parlant.
J’ai des questions à toutes vos réponses!
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager