传递参考和参考

时间:2014-05-11 18:08:22

标签: c#

我已经阅读了MSDN上的一些教程,以便了解C#,refout中的传递,我遇到了以下代码示例:

using System;

class TheClass
{
    public int x;
}

struct TheStruct
{
    public int x;
}

class TestClass
{
    public static void structtaker(TheStruct s)
    {
        s.x = 5;
    }
    public static void classtaker(TheClass c)
    {
        c.x = 5;
    }
    public static void Main()
    {
        TheStruct a = new TheStruct();
        TheClass b = new TheClass();
        a.x = 1;
        b.x = 1;
        structtaker(a);
        classtaker(b);
        Console.WriteLine("a.x = {0}", a.x); //prints 1
        Console.WriteLine("b.x = {0}", b.x); //prints 5
    }
}

教程中的注释:

  

此示例显示当结构传递给方法时,副本   传递结构,但是当传递类实例时,引用   通过了。

我完全理解它,但我的问题是,如果在C#中将引用传递给参数,为什么它们需要ref,如下例所示:

void tearDown(ref myClass a)
{
    a = null;
}

MyClass b = new MyClass();
this.tearDown(ref b);
assert(b == null);
//b is null

???我认为C#在C中是相同的 - 按值传递。

1 个答案:

答案 0 :(得分:7)

在C#中,基本上所有类都是指针。但是,通过ref / out传递或不传递就像将指针传递给指针或指针本身。

当您传递一个类(根据第一个示例)时,对成员类的任何更改都会被转移。但是,更改对对象本身的引用不会产生结果。说你替换

public static void classtaker(TheClass c)
{
    c.x = 5;
}

使用

public static void classtaker(TheClass c)
{
    c = new TheClass();
    c.x = 5;
}

由于c不是outref参数,您可以将本地指针重新分配给c,而不是c的值本身。由于您只修改了本地.x的{​​{1}},因此在调用此修改过的ClassTaker后,结果将是c

现在,根据您的第二个示例,由于a是b.x == 1参数,因此在调用范围中将看到对值本身的更改,如示例中所示,但是从ref中移除ref调用会导致null断言失败。

基本上,ref传递可以被认为是指向指针的指针,而没有ref / out的调用会将复制的指针传递给对象数据。


编辑:

可以在方法范围中指定c.X的原因是因为对象c 指向到对象X,并且您总是会得到无论X / ref参数如何,指向out的指针都相同。相反,ref / out会修改您更改调用范围所见的值c的能力。