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";
}
Était-ce utile?

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.

Ref dans variable de référence

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top