Quelle est l'utilisation de « ref » pour les variables de type référence en C #?
-
12-09-2019 - |
Question
Je comprends que si je passe une valeur de type (int
, struct
, etc.) comme paramètre (sans le mot-clé ref
), une copie de cette variable est passée à la méthode, mais si j'utilise le mot-clé ref
une référence à cette variable est passée, pas nouveau.
Mais avec référence-types, comme les classes, même sans le mot-clé ref
, une référence est passée à la méthode, pas une copie. Alors, quelle est l'utilisation du mot-clé ref
avec les types de référence?
Prenons par exemple:
var x = new Foo();
Quelle est la différence entre ce qui suit?
void Bar(Foo y) {
y.Name = "2";
}
et
void Bar(ref Foo y) {
y.Name = "2";
}
La solution
Vous pouvez modifier ce foo
points en utilisant y
:
Foo foo = new Foo("1");
void Bar(ref Foo y)
{
y = new Foo("2");
}
Bar(ref foo);
// foo.Name == "2"
Autres conseils
Il y a des cas où vous souhaitez modifier le réel référence et non l'objet pointé:
void Swap<T>(ref T x, ref T y) {
T t = x;
x = y;
y = t;
}
var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
Jon Skeet a écrit un grand article sur le passage de paramètres en C #. Il détaille clairement le comportement exact et l'utilisation des paramètres par valeur, par référence (ref
), et par la sortie (out
).
Voici une citation importante de cette page en fonction des paramètres de ref
:
Paramètres de référence ne passent pas valeurs des variables utilisées dans le membre fonction appel - ils utilisent les variables elles-mêmes. Plutôt que la création d'un nouvel emplacement de stockage pour la variable dans l'élément de fonction déclaration, le même emplacement de stockage est utilisé, de sorte que la valeur de la variable dans l'élément de fonction et de la valeur du paramètre de référence sera toujours être le même. Paramètres de référence doivent le modificateur ref dans le cadre à la fois du déclaration et l'invocation - que signifie qu'il est toujours clair quand vous êtes passer quelque chose par référence.
Très bien expliqué ici: http://msdn.microsoft.com/en-us/library/s6938f28.aspx
Résumé de l'article:
Une variable d'un type de référence ne contient pas les données directement; il contient une référence à ses données. Lorsque vous passez un type de référence paramètre par valeur, il est possible de modifier les données pointées par la référence, par exemple la valeur d'un élément de classe. Cependant, vous ne peut pas changer la valeur de la référence elle-même; qui est, vous ne pouvez pas utiliser la même référence à allouer de la mémoire pour une nouvelle classe et l'ont persister à l'extérieur du bloc. Pour ce faire, passer le paramètre à l'aide ref ou mot-clé sur.
Lorsque vous passez un type de référence avec le mot-clé ref, vous passez la référence par référence, et la méthode que vous appelez pouvez attribuer une nouvelle valeur au paramètre. Ce changement se propage à la portée d'appel. Sans référence, la référence est passé par valeur, et cela ne se produit pas.
C # a aussi le mot-clé « out » qui est un peu comme ref, sauf avec « ref », les arguments doivent être initialisées avant d'appeler la méthode, et « out » vous devez attribuer une valeur dans la méthode de réception.
Il vous permet de modifier la référence transmise. Par exemple.
void Bar()
{
var y = new Foo();
Baz(ref y);
}
void Baz(ref Foo y)
{
y.Name = "2";
// Overwrite the reference
y = new Foo();
}
Vous pouvez également utiliser sur si vous ne se soucient pas de la référence adoptée en:
void Bar()
{
var y = new Foo();
Baz(out y);
}
void Baz(out Foo y)
{
// Return a new reference
y = new Foo();
}
Un autre groupe de code
class O
{
public int prop = 0;
}
class Program
{
static void Main(string[] args)
{
O o1 = new O();
o1.prop = 1;
O o2 = new O();
o2.prop = 2;
o1modifier(o1);
o2modifier(ref o2);
Console.WriteLine("1 : " + o1.prop.ToString());
Console.WriteLine("2 : " + o2.prop.ToString());
Console.ReadLine();
}
static void o1modifier(O o)
{
o = new O();
o.prop = 3;
}
static void o2modifier(ref O o)
{
o = new O();
o.prop = 4;
}
}
En plus des réponses existantes:
Comme vous avez demandé la différence des 2 méthodes: Il n'y a pas d'écart CO (Nuestra) lors de l'utilisation ref
ou out
:
class Foo { }
class FooBar : Foo { }
static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }
void Main()
{
Foo foo = null;
Bar(foo); // OK
Bar(ref foo); // OK
FooBar fooBar = null;
Bar(fooBar); // OK (covariance)
Bar(ref fooBar); // compile time error
}
Un paramètre dans une méthode semble toujours passer une copie, la question est une copie de ce. Une copie est effectuée par un constructeur de copie pour un objet et que toutes les variables sont l'objet en C #, je crois que c'est le cas pour tous. Les variables (objets) sont comme les gens qui vivent à certaines adresses. Nous changeons les deux personnes qui vivent à ces adresses ou nous pouvons créer des références aux personnes vivant à ces adresses dans l'annuaire téléphonique (faire des copies peu profondes). Ainsi, plus d'un identifiant peut se référer à la même adresse. Les types de référence le désir de plus d'espace, donc à la différence des types de valeurs qui sont directement reliés par une flèche à leur identifiant dans la pile, ils ont une valeur pour une autre adresse dans le tas (un plus grand espace pour habiter). Cet espace doit être pris dans le tas.
Type de valeur: Indentifier (contient value = adresse de la valeur de la pile) ----> Valeur du type de valeur
Type de référence: Identificateur (contient value = adresse de la valeur de la pile) ----> (contient value = adresse de la valeur du segment de mémoire) ----> valeur Heap (le plus souvent contient des adresses d'autres valeurs), imaginer plusieurs flèches collant dans des directions différentes à la matrice [0], array [1], groupement [2]
La seule façon de changer une valeur est de suivre les flèches. Si une flèche se perd / a changé la façon dont la valeur est injoignable.
Variables de référence portent l'adresse d'un endroit à l'autre de sorte que toute updation sur eux en tout lieu réfléchira à tous les endroits alors quelle est l'utilisation de REF. variable de référence (405) sont bonnes jusqu'à ce qu'aucune nouvelle mémoire est allouée à la variable de référence passée dans la méthode.
Une fois que la nouvelle mémoire allouent (410), le changement de valeur sur cet objet (408) ne reflète pas partout. Pour cette ref vient. Ref est la référence de référence pour chaque fois qu'une nouvelle mémoire allouer il apprendre à connaître, car il pointe vers cet emplacement par conséquent, la valeur peut être partagée par tous. Vous pouvez voir l'image pour plus clearity.