944 votes

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

Je crée une fonction dans laquelle je dois 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 ?

81 votes

Vous : Je dois passer un objet pour qu'il puisse être modifié On dirait que MyClass serait une class c'est-à-dire un type de référence. Dans ce cas, l'objet que vous passez peut être modifié par la fonction myFunction même sans ref / out mot-clé. myFunction recevra un nouveau qui pointe vers le mismo et il peut modifier ce même objet autant qu'il le souhaite. La différence entre l ref Le mot-clé serait que myFunction a reçu le mismo référence au même objet. Cela ne serait important que si myFunction devaient changer la référence pour pointer vers autre objet.

4 votes

Je suis perplexe quant à la quantité de réponses confuses ici, alors que celle de @AnthonyKolesov est tout à fait parfaite.

0 votes

La déclaration d'une méthode out est utile lorsque vous souhaitez qu'une méthode renvoie plusieurs valeurs. Un argument peut être assigné à null. Cela permet aux méthodes de renvoyer des valeurs de manière facultative.

1227voto

Rune Grimstad Points 17775

ref indique 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.

Ainsi, alors que ref est à double sens, out est uniquement en sortie.

285 votes

Une autre particularité de out est que la fonction doit être assignée au paramètre out. Il n'est pas permis de le laisser sans affectation.

8 votes

Le terme "ref" ne s'applique-t-il qu'au type de valeur ? Puisque le type de référence est toujours passé par ref.

3 votes

Oui. Types de valeurs, y compris les structures

570voto

Anthony Kolesov Points 1156

En ref signifie que :

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

En out signifie que :

  1. La valeur n'est pas définie et ne peut pas être lue par la méthode jusqu'à il est fixé.
  2. La méthode debe le régler avant de repartir.

33 votes

Cette réponse explique de la manière la plus claire et la plus concise les restrictions imposées par le compilateur lors de l'utilisation du mot-clé out par rapport au mot-clé ref.

6 votes

De MSDN : Un paramètre ref doit être initialisé avant d'être utilisé, tandis qu'un paramètre out ne doit pas être explicitement initialisé avant d'être transmis et toute valeur précédente est ignorée.

1 votes

Avec out Le fichier peut-il être lu au sein de la méthode, avant qu'il n'ait été défini par cette méthode, s'il a été initialisé avant l'appel de la méthode ? Je veux dire, la méthode appelée peut-elle lire ce que la méthode appelante lui a transmis en tant qu'argument ?

151voto

Michael Blackburn Points 589

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

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

Si Dom était un argument de poids, il demanderait à Peter d'imprimer une nouvelle copie du mémo pour qu'il l'emporte avec lui.

55 votes

Ref Dom aurait écrit le rapport au crayon pour que Peter puisse le modifier

6 votes

@Deebster tu sais, cette métaphore ne t'a jamais rien fait, pourquoi dois-tu la torturer ainsi ? ;)

22 votes

Le site de stackoverflow a besoin de plus d'articles comme celui-ci.

62voto

James Roland Points 2582

Je vais tenter une explication :

Je pense que nous avons compris comment fonctionnent les types de valeurs, n'est-ce pas ? Les types de valeurs sont (int, long, struct, etc.). Lorsque vous les envoyez à une fonction sans commande ref, elle COPIE la valeur 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 réelles et toute modification affectera les données en dehors de la fonction.

Passons maintenant à la partie la plus déroutante, les types de référence :

Créons un type de référence :

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

Quand vous vous réveillez un objet Deux parties sont créées :

  1. Le bloc de mémoire qui contient les données pour un objet .
  2. Une référence (pointeur) à ce bloc de données.

Maintenant, lorsque vous envoyez un objet dans une méthode sans ref il COPIE le référence le pointeur, PAS les données. Voici donc ce que vous obtenez :

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

Deux références pointant vers le même objet. Si vous modifiez une propriété de un objet en utilisant la référence 2, il affectera les mêmes données que celles pointées par la référence 1.

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

Si vous annulez la référence 2 ou si vous la faites pointer vers de nouvelles données, cela n'affectera pas la référence 1 ni les données vers lesquelles la référence 1 pointe.

(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

Que se passe-t-il lorsque vous envoyez un objet par référence à une méthode ? La méthode référence réelle a un objet 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 cela signifie ? C'est exactement la même chose que d'envoyer un objet sans ref, à l'exception de deux points essentiels :

1) Lorsque vous annulez la référence à l'intérieur de la méthode, la référence à l'extérieur de la méthode est annulée.

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

2) Vous pouvez maintenant faire pointer la référence vers un emplacement de données complètement différent et la référence à l'extérieur de la fonction pointera désormais vers le nouvel emplacement de données.

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

0 votes

Vous voulez dire qu'après tout (dans le cas de ref) il n'y a qu'une seule référence aux données mais deux alias pour celles-ci. N'est-ce pas ?

4 votes

Upvoted pour la clarté de l'explication. Mais je pense que cela ne répond pas à la question, car cela n'explique pas la différence entre ref y out paramètres.

1 votes

Etonnant. Pouvez-vous expliquer la même chose que pour out mot-clé ?

29voto

Ruben Bartelink Points 23945

ref est en et sortir .

Vous devez utiliser out de préférence lorsqu'il répond à vos besoins.

0 votes

Pas tout à fait, car la réponse acceptée est ref si elle est directionnelle et inutile en ignorant les types de valeur si elle n'est pas retransmise.

0 votes

@kenny : Pouvez-vous clarifier un peu, s'il vous plaît - c'est-à-dire, quels mots changeriez-vous pour maintenir l'esprit de la réponse mais supprimer l'imprécision que vous percevez ? Ma réponse n'est pas une supposition farfelue de la part d'un débutant, mais la précipitation (laconisme, fautes de frappe) de votre commentaire semble supposer que c'est le cas. L'objectif est de fournir une façon de penser à la différence avec le moins de mots possible.

0 votes

(Je connais les types de valeur, les types de référence, le passage par référence, le passage par valeur, COM et C++ si vous jugez utile de faire référence à ces concepts dans votre clarification).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X