Comme nous le savons tous, les objets C # cles sont traités comme des références, alors que se passe-t-il lorsque vous transmettez un objet de référence comme référence à une méthode? Dire que nous avons: et ensuite: p> est le compilateur que le compilateur découvre que Et si nous avons quelque chose comme ceci: p> a code> est déjà un Type de référence et conservez-le ainsi, ou il crée une nouvelle référence à cet objet? P>
public void F(ref A a)
{
F(ref a);
}
6 Réponses :
Simplement indiqué, passez une variable sous forme de paramètre Réf, c'est comme créer un alias pour la variable d'origine.
Les types de référence et les paramètres de référence sont des entités distinctes. Dans C # Variables, on passe toujours de la valeur. Cette valeur peut être une référence à un autre objet ou une valeur stockée. P>
En d'autres termes, les types de référence sont "passés par référence" car lorsque vous passez une instance d'objet à une méthode, la méthode obtient une référence à l'instance d'objet.
Dans le cas de paramètres de référence, la référence est à la variable (donc pourquoi il est logique de penser à cela un alias). Ceci est une forme différente de "passage par référence". P>
aller par votre exemple: p> ici c'est comme nous avons un seul objet (l'original paramètre Voir la section 1.6.6.1 de La spécification 4.0 C # pour plus d'informations. p> p> A code>) qui est référencé des temps infinis. (Notez que ce n'est pas ce que réellement em> arrive). Ce diagramme est destiné à fournir une représentation idiomatique de ce qui se passe sous les couvercles lorsqu'il s'agit de paramètres de référence. p>
p>
Nope, A code> n'est pas un objet, c'est une référence à une variable contenant une référence à un objet.
@Benvoigt - Je veux dire qu'il peut être traité comme un seul objet, pas qu'il s'agisse d'un seul objet. Notez ce que j'ai dit à propos de "Alias". S'ils veulent tous les détails Nitty Gritty, ils peuvent voir la partie de la spécification que j'ai référencée.
En outre, cela n'a aucun sens de dire que "les variables sont toujours passées par la valeur". "Pass par valeur" implique le passage du paramètre, c'est-à-dire un argument, pas une variable.
@Benvoigt - respectueusement, je suis en désaccord. Eric Lippert a dit cela plusieurs fois (et je crois que Jon Skeet a dit la même chose dans une réponse par courrier électronique qu'il m'a envoyée une fois). De plus, pour moi, cela a beaucoup de sens lorsque vous envisagez "Paramètre de valeur" tel que défini dans la même section de la spécification.
Les variables sont des valeurs. Ils ne sont pas "passagers par valeur". "Pass par X" n'a de sens que lorsque vous parlez d'un paramètre, qui est passé.
@Benvoigt - Vous parlez de sémantique. Je parle d'intuition. Si l'OP veut la sémantique, il peut voir la spécification. Je propose un exemple intuitif qui vaut mieux pour quelqu'un qui essaie de saisir un concept.
Les deux concepts ne sont pas les mêmes. Un paramètre de méthode peut être modifié par référence, qu'il s'agisse d'un type de valeur ou d'un type de référence.
Passer un type par référence permet la méthode appelée pour modifier l'objet référé par le paramètre ou pour modifier l'emplacement de stockage du paramètre. . P>
static void Main() { Foo item = new Foo("aaa"); GetByReference(ref item); Console.WriteLine(item.Name) } static void ChangeByReference(ref Foo itemRef) { itemRef = new Foo("bbb"); }
Lorsque vous passez un objet comme paramètre d'une méthode, vous passez un nouveau pointeur qui fait référence à l'objet d'origine. Si vous passez un objet comme paramètre Réf, vous passez le même pointeur qui utilise la méthode de l'appelant. Un exemple, la sortie est 1 à 12 car le pointeur de l'objet B ne change pas mais l'objet d'origine change. P> p>
Ceci est mieux illustré avec un exemple: Que se passe-t-il? p> q1 et c1 se réfèrent au même objet mais sont différentes variables. Mutating C1.P Mutates Q1.P car les deux variables font référence au même objet, Q1 est maintenant 11. p> Q2 et C2 Reportez-vous au même objet, mais sont différentes variables. La mutation C2 ne mute pas q2 car c2 et q2 sont différentes variables; Changer on ne change pas l'autre. Q2 reste 2 et le nouvel objet est perdu. P> Q3 et C3 sont deux noms pour la même variable et font donc référence au même objet. Lorsque vous modifiez C3.p, modifie automatiquement Q3.P, car ils sont deux noms pour la même chose. P> Q4 et C4 sont deux noms pour la même variable, et par conséquent, la mutation du Q4 mutate également C4. p> Cela a un sens? p> Il est regrettable que le mot-clé de "faire un alias à cette variable" est "REF". Cela aurait été plus clair que c'était "alias". P> Pour répondre à votre deuxième question: Non, cela ne fait pas une chaîne de références. Faisons un exemple plus clair: p> Ceci indique que C1 et Q1 sont des noms différents pour la même variable, et Q1 et Q2 sont des noms différents pour la même variable, et donc C1, Q1 et Q2 sont tous des alias les uns des autres. Il n'y a jamais de "référence à une référence à la variable" en C # comme il existe en C ++. P> P>
Votre première méthode pourrait également être appelée comme m (q1, q2, ref qseame, ref qSame); code> et ensuite nous voyons qu'il est significatif que la ligne
c3.p = 13; code> est avant la ligne
c4 = nouveau c () {p = 14}; code> à l'intérieur de cette méthode.
Merci beaucoup, excellente réponse !!! Je n'aurais jamais pensé à ref code> comme
alias code>, c'est vrai ce que vous dites sur le problème de nommage, le concept pourrait être mal compris. Merci beaucoup à nouveau.
@ E.Campver: La chose est, dans le système de type CLR, il existe des types de référence et il existe des types de "référence aux variables", et ils sont logiquement différents. Un paramètre REF provient de la perspective du système de type CLR A "Référence à la variable", mais à partir du point de vue du système de type C #, cela ressemble plus à un alias.
ref code> crée simplement une référence à la valeur d'origine. Avec référence em> types de "valeur" est l'emplacement de la mémoire de la variable. Lorsque vous utilisez
ref code> la méthode peut maintenant modifier la référence de la variable d'origine. Si vous faites la même chose avec un argument qui est déjà
ref code> la 2e méthode a simplement la même référence que la première méthode a fait. P>
Dans un appel comme la variable d'autre part, dans un appel comme p> la variable à Vérifiez votre compréhension du paramètre de paramètre de valeur avec un paramètre de type code> de type code>, déterminez quelles sont ces méthodes: p> Voici un exemple éventuellement intéressant avec < Code> ref code>: p> comme exemple d'utilisation de A code> est "utilisé directement" par le corps de la méthode
f code>. Il n'y a qu'un seul emplacement de stockage. Si la méthode
f code> attribue à son paramètre, cette affectation sera visible à tous ceux qui peuvent voir
a code>, immédiatement. Et inversement, si quelqu'un (extérieur
f code>) attribue à
a code> pendant la méthode
f code> exécute, puis le paramètre de
f code > changera au nouvel objet "tout d'un coup". p>
Un code> est d'abord copié à une nouvelle variable, puis la nouvelle variable est utilisée à l'intérieur
f code>. Maintenant, si le type de paramètre de
f code> est un type type em> (comme un
struct code> ou
Enum code>), copier em> strong> est fait par valeur em>. De sorte que toutes les données sont copiées. Mais si le type de paramètre est un Type de référence em> (
class code> (type de tableau),
interface code>,
délégué code> ), la copie de
a code> implique une copie
g code> ci-dessus, considérez le code
var x = " initiale"; G (réf x, ref x); code> auquel cas
A code> va changer avec
B code> à l'intérieur de la méthode
g code>. p> p>
Voir également par exemple Pourquoi utiliser mot-clé referf lorsque vous passez un objet? et les threads dans la section "liée" de la colonne à la Droite, à cette page.