Ref和Out之间的差异是啥? [复制]

Posted

技术标签:

【中文标题】Ref和Out之间的差异是啥? [复制]【英文标题】:What is diff Between Ref And Out? [duplicate]Ref和Out之间的差异是什么? [复制] 【发布时间】:2010-11-04 05:37:53 【问题描述】:

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

refout 有什么区别?我对何时使用refout 感到困惑。那么请说明refout的使用方法,以及在哪些情况下使用。

【问题讨论】:

这个重复:***.com/questions/388464/… 【参考方案1】: 当您传递一个初始化参数并且您希望方法/函数修改它时,您使用 Ref

您在传递未初始化的参数时使用 Out,并且该方法必须初始化并填充该参数(否则您会收到警告甚至错误)。

bool IsUserValid(字符串用户名);

void IsUserValid(string username, out bool valid);

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

【讨论】:

完美的解释简洁易懂谢谢【参考方案2】:

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

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

【讨论】:

【参考方案3】:

有什么更好的方式向您展示给您MSDN link ;)

来自该链接:

ref 和 out 之间的区别是微妙但重要。每种参数传递模式都旨在应用于略有不同的编程场景。 out 和 ref 参数的重要区别在于各自使用的明确赋值规则。

【讨论】:

【参考方案4】:

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

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

因此,下面的代码将编译:

bool TryParse(string text, out int result)

  if (text == null)
    return false;
  else
  
     // do the parsing
  

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

【讨论】:

【参考方案5】:

确实有 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"

因此,虽然 by referenceby value 对于引用类型而言是相似的,但如果您更改引用本身(而不是您的参考)。

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

public int SomeMethod1() 

    return 1;


public void SomeMethod2(out int num) 

    num = 1;

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

【讨论】:

以上是关于Ref和Out之间的差异是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

ref、val 和 out 对方法参数的含义是啥?

“...”和“...”之间有解释差异吗? [复制]

内部联接和简单联接之间是不是有任何性能差异? [复制]

“select *”和所有列的选择之间是不是存在速度差异? [复制]

术语“长度”和“大小”之间是不是存在技术差异(当然是在编程中)? [复制]

IQueryable 和 IEnumerable 之间差异的真实示例? [复制]