Question Quelle est la différence entre les mots-clés 'ref' et 'out'?


Je crée une fonction où j'ai besoin de passer un objet pour qu'il puisse être modifié par la fonction. Quelle est la différence entre:

public void myFunction(ref MyClass someClass)

et

public void myFunction(out MyClass someClass)

Lequel dois-je utiliser et pourquoi?


718
2017-12-23 09:16


origine


Réponses:


ref dit au compilateur que l'objet est initialisé avant d'entrer dans la fonction, tandis que out indique au compilateur que l'objet sera initialisé dans la fonction.

Donc pendant ref est deux voies, out est sorti seulement.


973
2017-12-23 09:18



le ref modificateur signifie que:

  1. La valeur est déjà définie et
  2. La méthode peut le lire et le modifier.

le out modificateur signifie que:

  1. La valeur n'est pas définie et ne peut pas être lue par la méthode jusqu'à c'est réglé.
  2. La méthode doit Réglez-le avant de revenir.

430
2017-12-23 12:40



Disons que Dom se présente au bureau de Peter à propos du mémo sur les rapports TPS.

Si Dom était un argument de ref, il aurait une copie imprimée du mémo.

Si Dom se disputait, il ferait imprimer à Peter une nouvelle copie du mémo pour qu'il l'emmène avec lui.


129
2018-03-23 19:33



Je vais essayer ma main à une explication:

Je pense que nous comprenons comment les types de valeur fonctionnent bien? Les types de valeur sont (int, long, struct etc.). Lorsque vous les envoyez dans une fonction sans commande ref, COPIES la Les données. Tout ce que vous faites à ces données dans la fonction n'affecte que la copie, pas l'original. La commande ref envoie les données ACTUAL et toute modification affectera les données en dehors de la fonction.

Ok sur la partie déroutante, les types de référence:

Permet de créer un type de référence:

List<string> someobject = new List<string>()

Quand vous êtes nouveau someobject, deux parties sont créées:

  1. Le bloc de mémoire contenant les données pour someobject.
  2. Une référence (pointeur) à ce bloc de données.

Maintenant, quand vous envoyez someobject dans une méthode sans ref il COPIE le référence pointeur, PAS les données. Donc, vous avez maintenant ceci:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Deux références pointant vers le même objet. Si vous modifiez une propriété sur someobject using reference2 affectera les mêmes données pointées par reference1.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

Si vous annulez reference2 ou que vous le pointez sur de nouvelles données, cela n'affecte pas reference1 et la référence de données1 ne l'est pas.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Maintenant, que se passe-t-il lorsque vous envoyez someobject par ref à une méthode? le référence réelle à someobject est envoyé à la méthode. Vous n'avez donc plus qu'une seule référence aux données:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

mais qu'est ce que ça veut dire? Il agit exactement de la même manière que l'envoi de someobject non par ref sauf pour deux choses principales:

1) Lorsque vous annulez la référence à l'intérieur de la méthode, elle annulera celle en dehors de la méthode.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) Vous pouvez maintenant pointer la référence vers un emplacement de données complètement différent et la référence en dehors de la fonction pointera maintenant vers le nouvel emplacement des données.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

44
2017-09-23 17:55



ref est en et en dehors.

Tu devrais utiliser out de préférence partout où cela est suffisant pour vos besoins.


26
2017-12-23 09:17



en dehors:

En C #, une méthode peut retourner une seule valeur. Si vous souhaitez renvoyer plusieurs valeurs, vous pouvez utiliser le mot clé out. Le modificateur out retourne en retour par référence. La réponse la plus simple est que le mot clé "out" est utilisé pour obtenir la valeur de la méthode.

  1. Vous n'avez pas besoin d'initialiser la valeur dans la fonction appelante.
  2. Vous devez affecter la valeur à la fonction appelée, sinon le compilateur signale une erreur.

ref:

En C #, lorsque vous transmettez un type de valeur tel que int, float, double etc. en tant qu'argument au paramètre method, il est passé par valeur. Par conséquent, si vous modifiez la valeur du paramètre, cela n'affecte pas l'argument dans l'appel de méthode. Mais si vous marquez le paramètre avec le mot-clé "ref", il reflétera dans la variable réelle.

  1. Vous devez initialiser la variable avant d'appeler la fonction.
  2. Il n'est pas obligatoire d'affecter une valeur au paramètre ref dans la méthode. Si vous ne changez pas la valeur, quel est le besoin de la marquer comme "ref"?

12
2018-04-01 18:31



Extension du chien, exemple de chat. La seconde méthode avec ref change l'objet référencé par l'appelant. D'où "Cat" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

10
2018-05-19 13:35



Puisque vous passez dans un type de référence (une classe) il n'y a pas besoin d'utiliser ref parce que par défaut seulement un référence à l'objet réel est passé et donc vous toujours changer l'objet derrière la référence.

Exemple:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

Tant que vous passez dans une classe, vous n'avez pas à utiliser ref si vous voulez changer l'objet dans votre méthode.


6
2017-12-23 10:57



ref et out se comportent de la même manière sauf les différences suivantes.

  • ref La variable doit être initialisée avant utilisation. out variable peut être utilisé sans affectation
  • out Le paramètre doit être traité comme une valeur non affectée par la fonction qui l'utilise. Donc, nous pouvons utiliser initialisé out paramètre dans le code appelant, mais la valeur sera perdue lorsque la fonction s'exécute.

5
2018-02-10 16:29



"Boulanger"

C'est parce que le premier change votre référence de chaîne pour pointer sur "Baker". Changer la référence est possible parce que vous l'avez passé via le mot-clé ref (=> une référence à une référence à une chaîne). Le second appel obtient une copie de la référence à la chaîne.

la corde ressemble à une sorte de spéciale au début. Mais la chaîne est juste une classe de référence et si vous définissez

string s = "Able";

alors s est une référence à une classe de chaînes contenant le texte "Able"! Une autre affectation à la même variable via

s = "Baker";

ne change pas la chaîne d'origine mais crée juste une nouvelle instance et laisse point à cette instance!

Vous pouvez l'essayer avec l'exemple de code suivant:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

Qu'attendez-vous? Ce que vous obtiendrez est toujours "Capable" parce que vous venez de définir la référence dans s à une autre instance alors que s2 pointe vers l'instance d'origine.

MODIFIER: string est également immuable, ce qui signifie qu'il n'y a simplement aucune méthode ou propriété qui modifie une instance de chaîne existante (vous pouvez essayer d'en trouver une dans les docs mais vous n'en finirez pas :-)). Toutes les méthodes de manipulation de chaîne retournent une nouvelle instance de chaîne! (C'est pourquoi vous obtenez souvent une meilleure performance en utilisant la classe StringBuilder)


4
2017-12-23 13:40