6
votes

Les listes sont-elles transmises par la valeur?

passer Type de valeur Paramètres aux fonctions de C # est de la valeur que Vous utilisez le mot-clé REF ou OUT sur le paramètre. Mais cela s'applique-t-il également à Types de référence ?

Spécifiquement, j'ai une fonction qui prend un ilist . La liste est-elle transmise à ma fonction être une copie de la liste avec une copie de ses objets contenus? Ou des modifications de la liste s'appliqueront-elles également à l'appelant? Si oui - Y a-t-il un moyen intelligent, je peux faire passer une copie? xxx


4 commentaires

Thx pour les réponses rapides! Était comme je m'attendais. Il suffit d'avoir un moment d'incertitude là-bas ..


Si vous vouliez faire quelque chose d'intelligent, vous pouvez faire une classe de liste de votre choix, implicitement jeté à IList en effectuant une copie. Le seul avantage que je peux voir, c'est qu'il m'empêche théoriquement de "oublier" de faire une copie lorsque vous passez une collection autour.


Non - Je ne veux pas faire ça .. Le constructeur de liste qui prenait iEnumerable semble être aussi intelligent que possible. Tout ce dont j'ai besoin..


Ne te blâme pas. Habituellement, j'utilise "intelligent" comme synonyme de "ne fais pas ça".


6 Réponses :


4
votes

La liste est transmise par référence. Si vous modifiez la liste dans une fonction de fonctionnement, vous modifiez également la liste de l'appelant.

Vous pouvez créer une copie d'une liste en créant un nouveau: xxx


0 commentaires

16
votes

Tous les paramètres sont passés par la valeur, sauf si vous utilisez explicitement ref ou out . Cependant, lorsque vous passez une instance d'un type de référence, vous passez la référence par valeur. C'est à dire. La référence elle-même est copiée, mais puisqu'elle est toujours pointée vers la même instance, vous pouvez toujours modifier l'instance via cette référence. C'est à dire. L'instance n'est pas copiée. La référence est.

Si vous souhaitez effectuer une copie de la liste elle-même, Liste a un constructeur pratique , qui prend un ienumerable .


2 commentaires

De plus, si vous modifiez la référence à l'intérieur du corps de la fonction, ce changement ne sera pas visible à l'appelant. +1 de moi.


@Aggelos: Exactement. C'est une propriété de réussite par valeur.



3
votes

Votre liste est adoptée par référence. Si vous souhaitez transmettre une copie de la liste, vous pouvez faire:

IList<Foo> clone = new List<Foo>(list);


1 commentaires

+1 pour l'explication: ... mais les modifications des éléments eux-mêmes seront prises en compte dans les deux listes.



1
votes

Lorsque vous passez le type de référence par la valeur (sans référence REF ou OUT), vous pouvez modifier ce type de référence à l'intérieur de cette méthode et toutes les modifications réfléchiront au code des appelants.

Pour résoudre votre problème, vous pouvez créer explicitement une copie et passer Cette copie à votre fonction ou vous pouvez utiliser: xxx


0 commentaires

0
votes

Lorsque vous passez des types de référence, vous passez la référence. C'est un concept important.

Si vous passez une référence

byref, vous passez la référence (pointeur) directement.

BYVAL, vous passez une copie de la référence (pointeur).

Une référence n'est pas l'instance référencée. Une référence est analogue à un pointeur.

Pour transmettre une copie de l'instance d'un référencétype, vous devez d'abord effectuer une copie vous-même et transmettre une référence à la copie. En tant que tel, vous ne modifiez pas l'instance originale.


0 commentaires

11
votes

Vous n'êtes pas seul; Cela confond beaucoup de gens.

Voici comment j'aime bien penser.

Une variable est un emplacement de stockage.

une variable peut stocker quelque chose d'un type particulier.

Il existe deux types de types: Types de valeur et types de référence.

La valeur d'une variable de type de référence est une référence à un objet de ce type. < p> La valeur d'une variable de type de valeur est un objet de ce type.

Un paramètre formel est une sorte de variable.

Il existe trois types de paramètres formels: paramètres de valeur , Paramètres Ref et Out Paramètres.

Lorsque vous utilisez une variable comme argument correspondant à un paramètre de valeur, la valeur de la variable est copiée dans le stockage associé au paramètre formel. Si la variable est de type de valeur, une copie de la valeur est effectuée. Si la variable est de type de référence, une copie de la référence est effectuée et les deux variables se réfèrent maintenant au même objet. De toute façon, une copie de la valeur de la variable est faite.

Lorsque vous utilisez une variable comme argument correspondant à un paramètre OUT ou REF Le paramètre devient un alias pour la variable . Lorsque vous dites: xxx

ce que vous dites est "X et Y sont maintenant la même variable ". Ils se réfèrent tous les deux à le même emplacement de stockage .

Je trouve beaucoup plus facile à comprendre que de réfléchir à la manière dont l'alias est réellement mis en œuvre - en faisant passer l'adresse gérée de la variable à Le paramètre formel.

est-ce clair?


0 commentaires