Utilisation du mot clé ‘ref’ en C #

Doublons possibles:
Pourquoi utiliser le mot-clé ref lors du passage d’un object?
Quand passer le mot-clé ref

Quelle est l’utilisation correcte du mot clé ‘ref’ en C #. Je crois qu’il y a eu beaucoup de discussions sur ce sujet, mais ce qui ne me semble pas clair est:

  1. Le mot clé ref est-il nécessaire si vous passez un object de référence? Je veux dire lorsque vous créez un object dans le tas, n’est-il pas toujours passé par référence. Est-ce que cela doit être explicitement marqué comme une référence?

Utiliser ref signifie que la référence est passée à la fonction.

Le comportement par défaut est que la fonction reçoit une nouvelle référence au même object. Cela signifie que si vous modifiez la valeur de la référence (par exemple, définissez-la sur un nouvel object), vous ne pointez plus l’object source d’origine. Lorsque vous passez à l’aide de ref le fait de changer la valeur de la référence modifie la référence source – car il s’agit de la même chose.

Considère ceci:

 public class Thing { public ssortingng Property {get;set;} } public static void Go(Thing thing) { thing = new Thing(); thing.Property = "Changed"; } public static void Go(ref Thing thing) { thing = new Thing(); thing.Property = "Changed"; } 

Alors si tu cours

 var g = new Thing(); // this will not alter g Go(g); // this *will* alter g Go(ref g); 

Il y a beaucoup de désinformation déroutante dans les réponses. La meilleure façon de comprendre cela est d’abandonner l’idée que “ref” signifie “par référence”. Une meilleure façon de penser à cela est que “ref” signifie “Je veux que ce paramètre formel du côté appelé soit un alias pour une variable particulière du côté de l’appelant”.

Quand tu dis

 void M(ref int y) { y = 123; } ... int x = 456; M(ref x); 

c’est-à-dire “lors de l’appel à M, le paramètre formel y du côté de l’appelé est un autre nom pour la variable x du côté de l’appelant”. L’affectation de 123 à y est identique à l’atsortingbution de 123 à x car il s’agit de la même variable , une variable portant deux noms.

C’est tout. Ne pensez pas aux types de référence, aux types de valeur ou à quoi que ce soit, ne pensez pas à passer par référence ou par valeur. Tout “ref” signifie “donne temporairement un deuxième nom à cette variable”.

Je crois que le mot-clé ref indique que vous passez l’object par référence, pas par valeur. Par exemple:

 void myfunction(ref object a) { a = new Something(); } 

changerait la valeur d’un dans la fonction appelante Cependant,

 void myfunction(object a) { a = new Something(); } 

changerait la valeur d’un localement, mais pas dans la fonction appelante. Vous pouvez toujours modifier les propriétés de l’élément, mais vous ne pouvez pas définir la valeur de l’élément lui-même. Par exemple; a.someproperty = value;

fonctionnerait dans les deux cas.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace InOutRef { static class InOutRef { public static void In(int i) { Console.WriteLine(i); i=100; Console.WriteLine(i); } public static void Ref(ref int i) { Console.WriteLine(i); i=200; Console.WriteLine(i); } public static void Out(out int i) { //Console.WriteLine(i); //Error Unsigned Ref i=300; Console.WriteLine(i); } } class Program { static void Main(ssortingng[] args) { int i = 1; InOutRef.In(i); //passed by value (in only) Debug.Assert(i==1); InOutRef.Ref(ref i); //passed by ref (in or out) Debug.Assert(i == 200); InOutRef.Out(out i); //passed by as out ref (out only) Debug.Assert(i == 300); } } } 

Je ne peux pas être plus littéral dans ma réponse. Le code ne se souviendra pas des changements de référence tels que la question de l’ échange Java classique lorsqu’il est utilisé dans . Cependant, lors de l’utilisation de ref , ce sera similaire à VB.NET car il se souviendra des changements entrants et sortants . Si vous utilisez le paramètre out , cela signifie qu’il doit être déclaré avant de retourner (ceci est imposé par le compilateur).

 Sortie:
 1 // 1 du principal 
 100 // 100 à partir de
 1 // 1 n'est pas mémorisé dans In
 200 // 200 de la référence
 // devrait être 200 ici mais out applique out param (non imprimé car mis en commentaire)
 300 // 300 est sorti seulement
 Appuyez sur n'importe quelle touche pour continuer .  .  .