2013-10-01 124 views
4

以下代码的输出令我感到惊讶。我认为“a”应该引用新创建的对象。有人可以解释为什么结果不是2?c#对象通过引用传递或按值传递

class Program 
{ 
    static void Main(string[] args) 
    { 
     aclass a = new aclass(); 
     Process(a); 
     Console.WriteLine(a.number); 

     Console.ReadLine(); 
    } 

    static void Process(aclass a) 
    { 
     aclass temp = new aclass(); 
     temp.number++; 
     //Console.WriteLine(temp.number); 

     a = temp; 
     a.number++; 
     //Console.WriteLine(a.number); 
    } 

} 

class aclass 
{ 
    public int number = 0; 
} 

编辑:这是一个面试问题。我刚刚意识到我很长时间以来误解了这个概念。参数a与原始a不同,尽管它们引用相同的地址。

+2

因为当你做一个'= temp'你会被传入的说法,哪些是你将要起便修改之间的脱节。如果你没有这样做,你会在'Main'中获得'1'。 – Jon

+0

在c#中,参数值不是通过引用传递的,请查看[ref](http://msdn.microsoft.com/en-us/library/14akc2c7.aspx)关键字。 –

+1

你在'temp'上增加了'number'两次,但是你没有对'Main'中定义的'a'做任何工作。 – Sam

回答

10

你并没有改变实际的原始引用,你只是改变参数中保持的引用,这个引用微妙地不一样,所做的修改不会被保存回调用者。您可以使用outref来更改此行为。

在这种情况下,特别是你想使用ref因为你也顺带参考

尝试:

class Program 
{ 
    static void Main(string[] args) 
    { 
     aclass a = new aclass(); 
     Process(ref a); 
     Console.WriteLine(a.number); 

     Console.ReadLine(); 
    } 

    static void Process(ref aclass a) 
    { 
     aclass temp = new aclass(); 
     temp.number++; 
     //Console.WriteLine(temp.number); 

     a = temp; 
     a.number++; 
     //Console.WriteLine(a.number); 
    } 

} 

记住你与a = temp分配一个全新的基准。如果你只是想更新你在最初传递现有的类,那么你可以这样做:

a.number = temp.number; 
a.number++; 

这将否定了ref的需要。

你可以阅读更多的MSDN:

Passing Reference Type Parameters

ref Keyword

out Keyword

+0

这澄清了我对论点和原始对象的误解。参数a与原始a不同,但最初引用的是相同的值。 – mortdale

0

此行aclass a = new aclass();创建一个变量(空间,我们可以存储数据)在内存中。考虑到其在内存中的地址是*(0x12DF)并存储在该位置的value为对象a

此行Process(a)传递对象的VALUEa不是地址运作Process,所以有什么事情发生在Process()无关与contents的地址*(0x12DF)相关,因此地址*(0x12DF)的内容将保持与拨打Process()之前的相同。

*(0x12DF)内容=一

我希望它有帮助的,而不是创造更多的混乱!

+0

我认为_Process(a)_传递内容的地址。 _Process(aclass a)_中的参数是一个指向相同内容0x12DF的新对象。 0x12DF中的内容从未被复制过。传递地址比传递整个值更有效。如果_aclass_是一个值类型,则参数_a_将是一个新的对象,其值在不同的地址重复。 – mortdale

0

它基本上是

  • 按值传递引用类型之间的差//方法(a);
  • 通过引用传递引用类型// Process(ref a);

在示例中,Process(a) - 作为引用类型的'a'被传递给没有ref参数的方法。在这种情况下,将指向a的引用副本传递给该方法。

通过在Process方法中使用new运算符分配新内存部分,使得变量'a'引用了aclass的新对象。因此,之后的任何更改都不会影响原始对象'a'。

参见MSDN:http://msdn.microsoft.com/en-us/library/s6938f28.aspx