在方法中传递ref并且在C#中没有ref时有什么区别?

时间:2010-12-21 20:56:11

标签: c#

  

可能重复:
  When to pass ref keyword in

大家好,

我很惊讶为什么我们在C#中有ref,而默认情况下,C#中的所有引用类型都作为参考传递。

简单来说,任何人都可以解释这两种方法调用之间的区别:

public void Test(SomeClass someClass)
{
  // some code here
} 

public void Test(ref SomeClass someClass)
{
  // some code here
}

在我看来,他们都参考了相同的记忆位置。

那么为什么我们需要ref个关键字?

5 个答案:

答案 0 :(得分:8)

ref关键字传递对存储引用的任何位置的引用。这允许您从被调用函数中操作此变量。这对于值类型特别有用,但在与引用类型一起使用时也有用。 (Dictionary.TryGetValue()是一个很好的例子。out参数是返回存储在字典中的值所必需的。out相当于ref,除了它将经历一个不同的集合编译时检查。)

例如:

public void Test(ref SomeClass obj)
{
    obj = null;
}

public void Test2(SomeClass obj)
{
    obj = null;
}

public void Foo()
{
    SomeClass obj = new SomeClass();
    Test(ref obj);
    // obj is null here!

    obj = new SomeClass();
    Test2(obj);
    // obj is not null here.
}

答案 1 :(得分:3)

  

我很惊讶为什么我们在C#中使用ref,而默认情况下,C#中的所有引用类型都作为引用传递。

因为C#中的某些东西是值类型,有时我们想要传递它们。我们有ref关键字,以便这些内容也可以通过引用传递。

答案 2 :(得分:3)

这类似于C ++中SomeClass *SomeClass **之间的差异。

使用SomeClass *(或没有ref),我们可以修改指向的对象,但我们无法将其重定向到一个全新的对象。

使用SomeClass **(或ref),我们可以更改调用代码中的参数,以便将其指向我们选择的对象。

答案 3 :(得分:2)

传递对象时,通过引用传递它。这意味着在该方法返回后,您对该对象所做的任何操作都将反映在该对象中。当您通过引用传递引用,即void Foo(ref object obj)时,您将传递该对象的地址。然后,您可以将地址重新分配给另一个对象,这将是方法返回时的状态

foo (object o)
{
   ...
}

var v = new object();
foo(v);

v仍将引用在调用foo之前实例化的同一对象

void bar(ref object o)
{
   o = null;
}

var v = new object();
foo(ref v);
// v is now null

答案 4 :(得分:0)

假设方法Foo按值接受Bar。如果我有一个名为“Boz”的栏,声明:

  Foo(Boz);

可以使用Boz指向的对象并更改该对象的特征,但它不能更改 Boz指向的对象。相比之下,如果Boz通过引用传递,相同的语句可能会导致Boz完全指向不同的对象。

作为使用示例,请考虑接受数组作为参数的例程。如果按值传递数组,则收件人可以更改数组中任何项的值,但收件人无法更改大小。更改数组大小的唯一方法是创建一个新数组,将旧项复制到其中,然后使用新数组而不是旧数组。当一个数组按值传递时,收件人无法告诉调用者它应该停止使用旧数组并使用新数组。使用引用传递的数组不是问题。