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

C# Ref和Out之间的差异是什么?,c#,.net,syntax,C#,.net,Syntax,可能重复: ref和out之间有什么区别?我对何时使用ref和out感到困惑。因此,请解释如何使用ref和out,以及在哪些情况下使用。有什么更好的方式向您展示 从该链接: ref和out之间的差异很细微,但很重要。每个参数传递模式的设计都适用于稍微不同的编程场景。out和ref参数之间的重要区别在于各自使用的明确分配规则 当您传递初始化的参数并且希望方法/函数对其进行修改时,可以使用Ref 当您传递一个未初始化的参数时,您将使用Out,该方法将必须初始化并填充该参数(否则会出现警告甚至错误

可能重复:


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

有什么更好的方式向您展示

从该链接:

ref和out之间的差异很细微,但很重要。每个参数传递模式的设计都适用于稍微不同的编程场景。out和ref参数之间的重要区别在于各自使用的明确分配规则

  • 当您传递初始化的参数并且希望方法/函数对其进行修改时,可以使用Ref
  • 当您传递一个未初始化的参数时,您将使用Out,该方法将必须初始化并填充该参数(否则会出现警告甚至错误)

    bool IsUserValid(字符串用户名)

    void IsUserValid(字符串用户名,out bool valid)


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

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


如果“按值”传递引用(即,没有“ref”或“out”),则无法更改引用(因此“new”将无法通过调用),但是仍然可以更改此引用指向的属性的值(如果类允许)。

通常不赞成使用(或滥用)out和ref,通常,返回一个包含需要“返回”的多个字段的结构或简单类要干净得多

对于ref vs.out,out需要一个未初始化的变量,除非在退出函数之前设置out参数,否则代码不会编译

因此,下面的代码不会编译:

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

ref不要求您设置它们。另外,正如Hans提到的,在使用ref时,您实际上可以“新建”引用类型的对象(因为您获得了对引用的引用,这大致相当于C++中的对象**指针)

实际上有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"
好的,现在通过引用(
ref
在C#中或
ByRef
在VB.Net中)传递对结构值的引用:

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参数,则必须用方法填充它(就像返回一样)。

重复:完美的解释简明易懂谢谢