2009-10-29 56 views
1

所以,如果我迭代使用foreach循环,我有一个里面的函数,需要从列表中迭代的对象的参数,并可以说我设置它的值是不同的。 为什么我不必使用或ref?我认为它只是通过价值传递,如果你没有使用或参考....我知道一个ref你必须已经初始化变量之前,你只需要在从方法返回之前设置它的值。传递由ref和out

看来,如果你迭代通过列表并传递一个对象在其实际通过引用。考虑下面的例子。

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; } 
    } 

输出:

SetFoo预:1 SetFoo内:1 ::
WithoutRef SetFoo发表:1 WithoutRef
SetFoo预:1 :: WithoutRef SetFoo
Inside:1 :: WithoutRef :: WithRef
SetFoo Post:1 WithoutRef :: WithRef

SetFoo前:2 SetFoo内部:2 ::
WithoutRef SetFoo帖子:2 WithoutRef
SetFoo前:2 :: WithoutRef SetFoo
内部:2 :: WithoutRef :: WithRef
SetFoo帖子:2 WithoutRef: :WithRef

设置间隔预:0设置间隔内:2 SetIPost:0

SetRefI预:0 SetRefI内部:3
SetRefI发表:3

我理解带整数示例的ref,但不是上面的Foo对象迭代示例。

谢谢!

回答

12

参考通过值。所以这个方法仍然可以改变对象的内容,但它不能改变你的变量引用哪个对象。

查看my article on parameter passing了解更多信息,以及我的文章约reference types and value types

+0

因此,在上面的情况下,我传递了对象Foo到我的SetFoo方法的参考。由于它共享相同的内存位置,如果我更改Bar的值,那么在退出我的函数后,Bar的值将与列表中Foo的实例的值相同?那么不需要我的SetFooRef方法呢? – Gabe 2009-10-29 15:24:33

+0

它仍然不同,如果你没有使用ref修饰符,你通过引用值传递对象而不是对象引用指针(可以这么说)。如果你将在方法内部构造一个全新的Foo对象,那么你的SetFooRef可能是有用的 - 这个新对象将在方法之外被“看到”。相反,如果没有引用,你可以改变对象属性等等,这些改变将在外面“看到”,但是如果你在一个参数变量上初始化一个新的Foo对象 - 它将只有本地范围,因为你将覆盖引用值。 – Audrius 2009-10-29 15:38:31

+0

好吧,这更有意义。所以对于整数示例,我通过SetI()的值传递它,但设置SetRefI()我通过引用指针传递呢? – Gabe 2009-10-29 15:45:20