引用类型作为值和引用参数

时间:2013-08-27 02:03:03

标签: c# reference-type

所以我通过Illustrated C#2012,我基本上得到了所有内容,但下面的这一部分是源代码:

class MyClass
{
    public int Val = 20;
}

class Program
{
    static void RefAsParameter(MyClass f1)
    {
        f1.Val = 50;
        Console.WriteLine( "After member assignment: {0}", f1.Val );
        f1 = new MyClass();
        Console.WriteLine( "After new object creation: {0}", f1.Val );
    }

    static void Main()
    {
        MyClass a1 = new MyClass();
        Console.WriteLine( "Before method call: {0}", a1.Val );
        RefAsParameter( a1 );
        Console.WriteLine( "After method call: {0}", a1.Val );
    }
}

此代码生成以下输出:

Before method call: 20
After member assignment: 50
After new object creation: 20
After method call: 50

所以...我基本上了解到最后一个Console.WriteLine()。为什么在方法调用之后是50“。既然它创建了一个新的“MyClass()”它不应该仍然是20?显然我错过了一些非常明显的东西。是因为f1.Val改变了Myclass Public值“for good”还是什么?

对此略有困惑。谢谢。 我理解“参考文献”一般来说这个我只是有点难过。

3 个答案:

答案 0 :(得分:3)

该行

f1 = new MyClass();

重新指定变量f1以指向新的MyClass。它不会更改a1变量。

如果您将方法更改为:

static void RefAsParameter( ref MyClass f1 )

然后更改a1变量,您将获得:

After method call: 20

答案 1 :(得分:3)

看哪..我很棒的油漆技巧:

enter image description here

Click here for the full image

在方法中使用f1时,它是新引用,指向内存中的同一对象。当您使用f1 = new MyClass();重新分配引用时,您实际上是在说“好吧,此引用现在指向一个新实例”。这使a1保持不变..因此,当函数展开并点击Console.WriteLine时,您的a1引用仍引用旧的内存区域...现在属性设置为50。 / p>

要获得您期望的行为,请将对象作为ref参数传递:

static void RefAsParameter(ref MyClass f1)

答案 2 :(得分:1)

引用对象时,并不意味着它本身就是在复制。这意味着我们指向具有两个不同名称的同一对象。此处a1f1都引用了相同的对象,这就是为什么我们使用f1更改值时所以a1的值也在变化。

稍后您将创建另一个实例并将引用分配给f1。因此,现在f1将无法再访问上一个对象,现在a1f1将不会引用同一个对象。