如果我将一个对象传递给一个方法,为什么我应该使用ref关键字?这难道不是默认的行为吗?

例如:

class Program
{
    static void Main(string[] args)
    {
        TestRef t = new TestRef();
        t.Something = "Foo";

        DoSomething(t);
        Console.WriteLine(t.Something);
    }

    static public void DoSomething(TestRef t)
    {
        t.Something = "Bar";
    }
}


public class TestRef
{
    public string Something { get; set; }
}

输出是“Bar”,这意味着对象作为引用传递。


当前回答

通过对引用类型使用ref关键字,可以有效地将引用传递给引用。在许多方面,这与使用out关键字是相同的,但有一个微小的区别,即不能保证该方法实际会将任何东西赋值给ref'ed形参。

其他回答

你需要区分“通过值传递引用”和“通过引用传递参数/参数”。

我写了一篇相当长的关于这个主题的文章,以避免每次在新闻组上出现这个问题时都要仔细写

由于TestRef是一个类(它是引用对象),您可以在不将t作为引用传递的情况下更改t内部的内容。然而,如果您将t作为引用传递,TestRef可以更改原始t所引用的内容。也就是说,让它指向一个不同的对象。

这就像在c中传递一个指针给另一个指针一样,在。net中,这将允许你改变原来的T指的是什么,尽管我个人认为,如果你在。net中这样做,你可能有一个设计问题!

如果你想改变对象是什么,传递一个ref:

TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);

void DoSomething(ref TestRef t)
{
  t = new TestRef();
  t.Something = "Not just a changed t, but a completely different TestRef object";
}

调用DoSomething之后,t并不指向原来的新TestRef,而是指向一个完全不同的对象。

如果你想改变一个不可变对象的值,比如一个字符串,这可能也很有用。一旦创建了字符串,就不能更改它的值。但是通过使用ref,您可以创建一个函数,将字符串更改为另一个具有不同值的字符串。

除非需要,否则使用ref不是一个好主意。使用ref使方法可以自由地将参数更改为其他内容,因此需要对方法的调用者进行编码,以确保他们能够处理这种可能性。

同样,当参数类型是对象时,对象变量总是作为对象的引用。这意味着当使用ref关键字时,您获得了对引用的引用。这允许您按照上面给出的示例进行操作。但是,当形参类型是一个基元值(例如int)时,那么如果这个形参在方法中被赋值,传入的实参值将在方法返回后被更改:

int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10

void Change(ref int x)
{
  x = 5;
}

void WillNotChange(int x)
{
  x = 10;
}

通过对引用类型使用ref关键字,可以有效地将引用传递给引用。在许多方面,这与使用out关键字是相同的,但有一个微小的区别,即不能保证该方法实际会将任何东西赋值给ref'ed形参。