Pourquoi est liste lorsqu'il est passé sans ref à une fonction d'agir comme passé avec les ref?
Si je ne trouvais pas cela très mal, et ce comportement est étrange pour moi. Plutôt que d'expliquer, je vais poster un exemple de code ci-dessous et s'il vous plaît dites-moi pourquoi je obtenir une sortie de x et pas y.
private void button1_Click(object sender, EventArgs e)
{
List<int> l = new List<int>() { 1, 2, 3 };
Fuss(l);
MessageBox.Show(l.Count.ToString());
}
private void Fuss(List<int> l)
{
l.Add(4);
l.Add(5);
}
Sortie doit, je suppose, serait de 3. Mais je reçois la sortie 5. Je comprends la sortie peut être 5 si je fais ceci:
private void button1_Click(object sender, EventArgs e)
{
List<int> l = new List<int>() { 1, 2, 3 };
Fuss(ref l);
MessageBox.Show(l.Count.ToString());
}
private void Fuss(ref List<int> l)
{
l.Add(4);
l.Add(5);
}
Vous devriez également lire Jon Skeet Passage de paramètres en C#.
OriginalL'auteur nawfal | 2011-09-06
Vous devez vous connecter pour publier un commentaire.
Elle n'agit pas comme son passé par réf.
De l'essayer. Avez-vous remarqué la différence?
Vous ne pouvez modifier le contenu de la liste (ou tout type de référence) si vous passer sans un ref (parce que comme d'autres l'ont dit, vous pouvez passer une référence à l'objet sur le tas et donc le changement de la même "mémoire").
Cependant vous ne pouvez pas modifier "liste", "liste" est une variable qui pointe vers un objet de type Liste. Vous pouvez uniquement modifier la liste " si vous passer par référence (pour que ce point d'ailleurs). Vous obtenez une copie de la référence, qui, si changé, ne peut être observé à l'intérieur de votre méthode.
OriginalL'auteur chrisaut
Les paramètres sont passés par valeur en C#, sauf s'ils sont marqués avec le
ref
ouout
modificateurs. Pour les types référence, cela signifie que la référence est passé par valeur. Par conséquent, dansFuss
,l
est en se référant à la même instance deList<int>
comme son appelant. Par conséquent, toute modification à la présente instance deList<int>
sera vu par l'appelant.Maintenant, si vous activez le paramètre
l
avecref
ouout
, puis le paramètre est passé par référence. Ce que cela signifie est que, dansFuss
,l
est un alias pour l'emplacement de stockage utilisé comme paramètre pour appeler la méthode. Pour être clair:appelé par
Maintenant, dans
Fuss
,l
est un alias pourlist
. En particulier, si vous affectez une nouvelle instance deList<int>
àl
, l'appelant ne voir que la nouvelle instance affectée à la variablelist
. En particulier, si vous ditesalors le visiteur va maintenant voir une liste avec un seul élément. Mais si vous dites
et de les appeler par
alors le visiteur va encore voir
list
de trois éléments.Clair?
l
, il ne pourra pas se reflète dans l'appelant. Mais comment ça se reflète dans mon problème, j'ai posé sans ref?Je pense que @Steven 's réponse précise de votre réponse pour moi. C'est sans ref, je peux modifier le contenu de la liste, mais pas la liste elle-même! Avec les ref je peux faire les deux, il me semble.
Dans le second cas, à la fois de l'appelé et de l'appelant sont se référant à la même instance de
List<int>
, alors, évidemment, ils ont tous les deux voir les changements. Dans le premier cas, à la fois de l'appelé et de l'appelant sont en utilisant le même emplacement de stockage. Il n'est donc pas juste qu'ils voient la mêmeList<int>
, mais ils peuvent changer d'instance deList<int>
les uns les autres à regarder!J'ai compris ce que vous dites. Un grand merci. Mais j'ai eu le point plus clair de FishBasketGordo et Steven. Permettez-moi de marquer leur. Ensemble, vous trois point clair pour moi.
OriginalL'auteur jason
La différence entre les ref et non-réf pour les types de référence comme la Liste n'est pas de savoir si vous passer une référence (qui se produit toujours), mais de savoir si cette référence peut être modifié. Essayez ce qui suit
et vous verrez le nombre est de 2, parce que la fonction n'est pas seulement manipulé la liste d'origine mais la référence elle-même.
OriginalL'auteur Tomas Vana
ByRef et ByVal s'appliquent uniquement aux types de valeurs, pas pour les types référence, qui sont toujours passés comme s'ils étaient "byref".
Si vous avez besoin de modifier une liste discrètement, utiliser le ".ToList ()", et vous obtiendrez un clone de votre liste.
Garder à l'esprit que si votre liste contient les types référence, votre "nouvelle" liste contient des pointeurs vers les objets mêmes que l'original de votre liste.
En outre, vous pouvez aussi vous un .méthode clone()
OriginalL'auteur Wesley Long
Listes sont déjà des types de référence, de sorte que lorsque vous passez à une méthode, vous êtes de passage à une référence. Tout
Add
appels affecte la liste de l'appelant.Le passage d'un
List<T>
parref
se comporte essentiellement comme le passage d'un double pointeur à cette liste. Voici une illustration:OriginalL'auteur FishBasketGordo
Une variable, un paramètre ou d'un champ de type "Liste", ou tout autre type de référence, n'est pas réellement tenir une liste (ou d'un objet d'une autre catégorie). Au lieu de cela, il en sera quelque chose comme "Object ID #29115" (pas une chaîne réelle, bien sûr, mais d'une combinaison de bits, ce qui signifie essentiellement que). D'ailleurs, le système sera indexé de la collection d'objets appelé le tas; si une variable de type Liste contient les "Object ID #29115", puis l'objet #29115 dans le tas qui sera une instance de Liste ou d'un certain type qui en sont dérivés.
Si MyFoo est une variable de type Liste, un énoncé comme " MyFoo.Add("George")' ne sera pas réellement changer MyFoo; au lieu de cela, il signifie "Examiner l'ID de l'objet stocké dans MyFoo, et d'invoquer le "Ajouter" une méthode de l'objet qui y sont stockées. Si MyFoo tenue "Object ID #19533" avant l'exécution d'une instruction, il continuera de le faire après, mais Object ID #19533 aura eu sa méthode Add invoquée (probablement de l'altération de cet objet). À l'inverse, un énoncé comme "MyFoo = MyBar" fera MyFoo de tenir le même objet-id comme MyBar, mais ne sera pas réellement faire quelque chose pour que les objets en question. Si MyBar tenue "Object ID #59212" avant de faire la déclaration, puis, après la déclaration, MyFoo tiendra également "ObjectId #59212". Rien ne va arriver à object ID #19533, ni object ID#59212.
OriginalL'auteur supercat
Seulement les types primitifs comme int, double, etc. sont passés par valeur.
Types complexes (comme la liste) sont passés par référence (qui est au passage du pointeur de la valeur, pour être exact).
ref
ouout
.Donc, quel point dans ma réponse est fausse?
Vous avez dit "Seuls les types primitifs...sont passés par valeur. Les types complexes...sont passés par référence." Comme je l'ai dit, tous les paramètres sont passés par valeur, à moins marquée avec
ref
ouout
, pas "seulement les types primitifs.". "Complexe" n'est pas un terme bien défini; je suis en supposant que vous dire de types de référence. Les paramètres de type de types de référence sont passés par valeur, à moins d'être marqué avecref
ouout
.Non, je voulais dire que la méthode n'est pas la copie de l'objet, mais seulement son adresse. Pensez-y comme en c++, où vous n'avez pas de mot-clé "ref". Relire attentivement. Je suis d'accord avec votre point de vue sur "complexe", refernce serait un meilleur mot.
C# est pas du C++. "Non, je voulais dire que la méthode n'est pas la copie de l'objet, mais seulement son adresse." En mettant de côté la médiocrité ("la méthode n'est pas la copie de l'objet"), la valeur est copiée avant d'être transmis à la méthode. Toujours, toujours, toujours (à moins d'être marqué avec
ref
ouout
). Pour les types de valeur, l'instance est la valeur. Pour les types référence, la valeur est la référence. Notez que ce n'est pas le même que le référent!OriginalL'auteur deha