什么是Ref和Out之间的差异?

时间:2009-06-19 06:28:36

标签: c# .net syntax

  

可能重复:
  Whats the difference between the 'ref' and 'out' keywords?

refout之间有什么区别?我对何时使用refout感到困惑。因此,请说明如何使用refout以及在哪些情况下使用。

5 个答案:

答案 0 :(得分:14)

  • 传递初始化参数时,使用参考,并希望方法/函数对其进行修改。
  • 传递未初始化的参数时使用 Out ,该方法必须初始化并填充该参数(否则会收到警告甚至错误)。

    bool IsUserValid(字符串用户名);

    void IsUserValid(string username,out bool valid);

上述声明大致相同。返回值更容易,因此在这种情况下,您将使用返回类型。但是如果你的方法还需要返回用户的出生日期,你不能在返回中返回两个参数,你必须使用out参数来返回其中一个(或者使方法无效并将两者都返回)。

答案 1 :(得分:2)

需要注意的一点是(不)使用带参考类型参数的“ref”。 “ref”用于引用本身,而不是引用指向的对象的内容。

如果您通过“按值”传递参考(即没有“参考”或“输出”),则无法更改参考(因此“新”将无法生效但是,您仍然可以更改此引用指向的属性的值(如果类允许的话)。

答案 2 :(得分:1)

更好的方式来向您展示MSDN link;)

来自该链接:

  

ref和out之间的区别是微妙但重要。每个参数传递模式都适用于稍微不同的编程方案。 out和ref参数之间的重要区别在于每个参数使用的明确赋值规则。

答案 3 :(得分:1)

通常不赞成使用(或滥用)out和ref,通常返回结构或简单类更清晰,包含你需要“返回”的多个字段。

对于ref与out,out需要一个未初始化的变量,除非在退出函数之前设置out参数,否则代码将无法编译。

因此,下面的代码 编译:

bool TryParse(string text, out int result)
{
  if (text == null)
    return false;
  else
  {
     // do the parsing
  }
}

ref不需要您设置它们。同样正如汉斯提到的那样,当使用ref时,你实际上可以“新”引用类型的对象(因为你得到对引用的引用,它大致等于C ++中的对象**指针)

答案 4 :(得分:0)

确实有3种方法可以将参数传递给方法:按引用按值作为输出

按值是默认值,并且在C#中没有关键字(它在VB.Net:ByVal中) - 它传递了值类型的副本:

public void SomeMethod1(int num) 
{
    num = 2;
}

int myNum = 1;
SomeMethod1( myNum  );
// myNum is still 1, we just set a new one

令人困惑 - 按值为参考类型传递参考的副本。这意味着您对引用类型的更改将指向实例,但您只有指向引用的实际指针的副本:

public void SomeMethod1(MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 1";

    // we're only nulling the copy passed to this method
    instance = null;
}

public void SomeMethod2(MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 2";

    // this is a new instance only in this method
    instance = new MyClass { Name = "new instance" };
}

MyClass myInst = new MyClass { Name = "original" };
SomeMethod1( myInst );
// myInst.Name is now "test 1"

SomeMethod2( myInst );
// myInst.Name is now "test 2"

好的,现在通过引用(C#中的ref或VB.Net中的ByRef)传递对结构的值的引用:

public void SomeMethod1(ref int num) 
{
    num = 2;
}

int myNum = 1;
SomeMethod1( ref myNum  );
// myNum is now 2, we changed the reference

很简单,但对于引用类型,通过引用将实际指针传递给实例,而不是副本:

public void SomeMethod1(ref MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 1";

    // we're nulling the reference passed to this method
    instance = null;
}

public void SomeMethod2(ref MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 2";

    // this is a new instance replacing the original
    instance = new MyClass { Name = "new instance" };
}

MyClass myInst = new MyClass { Name = "original" };
SomeMethod1( ref myInst );
// myInst.Name will now throw a NullReferenceException because myInst is null

SomeMethod2( ref myInst );
// myInst.Name is now "new instance"

因此,虽然引用两者对于引用类型都相似,但如果您要更改引用本身(而不是您自己的行为),则行为非常明显参考)。

最后作为输出是一个额外的返回变量,就像实际的返回一样。这两个基本相同:

public int SomeMethod1() 
{
    return 1;
}

public void SomeMethod2(out int num) 
{
    num = 1;
}

如果你有一个out参数,它必须由方法填充(就像返回一样)。