2009-10-29 4 views
1

Donc si j'écrit en utilisant une boucle foreach et que j'ai une fonction dedans qui prend un argument de l'objet itéré de la liste, et disons que je définis sa valeur pour qu'elle soit différente. Pourquoi ne dois-je pas utiliser out ou ref? Je pensais que c'était seulement passé par valeur si vous n'utilisiez pas out ou ref .... Je sais qu'une ref que vous devez avoir initialisé la variable avant et après vous devez juste avoir défini sa valeur avant le retour de la méthode.Passant Par ref et out

Il semble que vous parcouriez une liste et que vous passiez un objet dans son passé par référence. Considérez l'exemple suivant.

Exemple

class Program 
    { 
     static void Main(string[] args) 
     { 

      List<Foo> list = new List<Foo>(); 
      list.Add(new Foo() { Bar = "1" }); 
      list.Add(new Foo() { Bar = "2" }); 



      foreach (var f in list) 
      { 
       Foo f2 = f; 
       Console.WriteLine("SetFoo Pre: " + f2.Bar); 
       SetFoo(f2); 
       Console.WriteLine("SetFoo Post: " + f2.Bar); 

       Console.WriteLine("SetFooRef Pre: " + f2.Bar); 
       SetFooRef(ref f2); 
       Console.WriteLine("SetFooRef Post: " + f2.Bar); 
       Console.WriteLine(""); 
      } 




      Console.WriteLine(""); 

      int i = 0; 
      // Not using ref keyword 
      Console.WriteLine("SetI Pre: " + i); 
      SetI(i); 
      Console.WriteLine("SetI Post: " + i); 

      // Using ref keyword 
      Console.WriteLine("SetRefI Pre: " + i); 
      SetRefI(ref i); 
      Console.WriteLine("SetRefI Post: " + i); 
     } 


     private static void SetRefI(ref int i) 
     { 
      i = 3; 
      Console.WriteLine("SetRefI Inside: " + i); 
     } 

     private static void SetI(int i) 
     { 
      i = 2; 
      Console.WriteLine("SetI Inside: " + i); 
     } 

     private static void SetFooRef(ref Foo f) 
     { 
      f.Bar = String.Format("{0} :: {1}", f.Bar, "WithRef"); 
      Console.WriteLine("SetFooRef Inside: " + f.Bar); 
     } 

     private static void SetFoo(Foo f) 
     { 
      f.Bar = String.Format("{0} :: {1}", f.Bar, "WithoutRef"); 
      Console.WriteLine("SetFoo Inside: " + f.Bar); 
     } 
    } 


    class Foo 
    { 
     public string Bar { get; set; } 
    } 

Sortie:

setFoo Pre: 1 setFoo Intérieur: 1 ::
WithoutRef setFoo Poste: 1 WithoutRef
setFoo Pre: 1 :: WithoutRef setFoo
Intérieur: 1 :: WithoutRef :: WithRef
SetFoo Message: 1 WithoutRef :: WithRef

setFoo Pre: 2 setFoo Intérieur: 2 ::
WithoutRef setFoo Poste: 2 WithoutRef
setFoo Pre: 2 :: WithoutRef setFoo
Intérieur: 2 :: WithoutRef :: WithRef
setFoo Poste: 2 WithoutRef: : WithRef

SETI Pre: 0 SETI intérieur: 2 SetIPost: 0

SetRefI Pre: 0 SetRefI intérieur: 3
SetRefI Poste: 3

Je comprends le ref avec l'exemple entier mais pas l'exemple d'itération d'objet Foo ci-dessus.

Merci!

Répondre

12

La référence est transmise par valeur. Ainsi, la méthode peut toujours changer le contenu de l'objet, elle ne peut simplement pas changer l'objet auquel votre variable fait référence.

Voir my article on parameter passing pour plus d'informations, avec mon article sur reference types and value types.

+0

Donc dans le cas ci-dessus, je passe une référence de l'objet Foo à mes méthodes SetFoo. Puisqu'il partage l'emplacement de la mémoire sames, si je modifie la valeur de Bar, la valeur de Bar sera la même que celle de Foo dans la liste après avoir quitté ma fonction? Donc, il n'y a pas besoin de ma méthode SetFooRef alors? – Gabe

+0

Il est encore différent, vous passez et objet par la valeur de référence plutôt que le pointeur de référence de l'objet (pour ainsi dire) si vous n'utilisez pas le modificateur ref. Votre SetFooRef peut être utile si, disons, vous allez construire un objet Foo complètement nouveau dans la méthode - ce nouvel objet sera "vu" en dehors de la méthode. En revanche, sans ref, vous pouvez modifier les propriétés des objets, etc. et ces modifications seront "vues" à l'extérieur, mais si vous initialisez un nouvel objet Foo sur une variable de paramètre, elle n'aura qu'une portée locale. – Audrius

+0

Ok, ça a plus de sens. Donc pour l'exemple entier, je le passe par valeur avec SetI() mais setRefI() je passe par le pointeur de référence alors? – Gabe

Questions connexes