Ref和Out之间的区别是什么? [重复]

时间:2022-08-02 21:03:03

Possible Duplicate:
Whats the difference between the 'ref' and 'out' keywords?

可能重复:'ref'和'out'关键字之间有什么区别?

What is the difference between ref and out? I am confused about when to use ref and out. So please explain how to use ref and out, and in which situations.

ref和out有什么区别?我很困惑何时使用ref和out。所以请解释如何使用ref和out,以及在哪些情况下。

5 个解决方案

#1


  • You use Ref when you pass an initialized parameter and you expect the method/function to modify it.
  • 传递初始化参数时使用Ref,并期望方法/函数对其进行修改。

  • You use Out when you pass an un-initialized parameter and the method will have to initialize and fill that parameter (you get a warning or even error otherwise).

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

    bool IsUserValid(string username);

    bool IsUserValid(字符串用户名);

    void IsUserValid(string username, out bool valid);

    void IsUserValid(字符串用户名,输出bool有效);

The declarations above are roughly the same. It's easier to return the value, so in this case you will use the return type. But if your method also needs to return the birth date of the user you can't return both parameters in the return, you have to use out parameters to return one of them (or void the method and return both as out).

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

#2


One thing to watch out for is when (not) to use "ref" with reference-type parameters. The "ref" is for the reference itself, not for the contents of the object that the reference points to.

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

If you pass a reference "by value" (that is, without 'ref' or 'out'), you can't change the reference (so a "new" will not survive the call), you can however still change the values of the properties this reference points to (if the class allows so).

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

#3


what a better way to show you giving you an MSDN link ;)

有什么更好的方式来告诉你给你一个MSDN链接;)

from that link:

从该链接:

The difference between ref and out is subtle but important. Each parameter passing mode is designed to apply to a slightly different programming scenario. The important difference between out and ref parameters is the definite assignment rules used by each.

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

#4


It's generally frowned upon to use (or abuse) out and ref, often it's much cleaner to return a struct or simple class, containing the multiple fields you need to "return".

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

As for ref vs. out, out requires an un-initialized variable, and the code will not compile unless you set the out param before exiting the function.

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

The code below will therefore not compile:

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

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

ref's does not require you to set them. Also as Hans mentions you can actually "new" the object of a reference type when using ref (since you get a reference to the reference, which is roughly equal to a object** pointer in C++)

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

#5


Really there are 3 ways to pass a parameter to a method: by reference, by value and as output.

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

By value is the default and doesn't have a keyword in C# (it does in VB.Net: ByVal) - it passes a copy of value types:

按值是默认值,并且在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

Confusingly - By value passes a copy of the reference for reference types. That means that your changes to a reference type point back to the instance, but you only have a copy of the actual pointer to the reference:

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

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"

Ok, so now by reference (ref in C# or ByRef in VB.Net) passes a reference to the value for structs:

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

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

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

Simple enough, but for reference types by reference passes the actual pointer to the instance, not a copy:

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

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"

So while both by reference and by value are similar for reference types, the behaviour is very distinct if you are changing the reference itself (rather than what you're referring to).

因此,虽然引用和值的引用类型都相似,但如果您要更改引用本身(而不是您所指的引用),则行为非常不同。

Finally as output is an extra return variable, just like the actual return. These two are bascially the same:

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

public int SomeMethod1() 
{
    return 1;
}

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

If you have an out parameter it must be populated by the method (just like a return).

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

#1


  • You use Ref when you pass an initialized parameter and you expect the method/function to modify it.
  • 传递初始化参数时使用Ref,并期望方法/函数对其进行修改。

  • You use Out when you pass an un-initialized parameter and the method will have to initialize and fill that parameter (you get a warning or even error otherwise).

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

    bool IsUserValid(string username);

    bool IsUserValid(字符串用户名);

    void IsUserValid(string username, out bool valid);

    void IsUserValid(字符串用户名,输出bool有效);

The declarations above are roughly the same. It's easier to return the value, so in this case you will use the return type. But if your method also needs to return the birth date of the user you can't return both parameters in the return, you have to use out parameters to return one of them (or void the method and return both as out).

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

#2


One thing to watch out for is when (not) to use "ref" with reference-type parameters. The "ref" is for the reference itself, not for the contents of the object that the reference points to.

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

If you pass a reference "by value" (that is, without 'ref' or 'out'), you can't change the reference (so a "new" will not survive the call), you can however still change the values of the properties this reference points to (if the class allows so).

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

#3


what a better way to show you giving you an MSDN link ;)

有什么更好的方式来告诉你给你一个MSDN链接;)

from that link:

从该链接:

The difference between ref and out is subtle but important. Each parameter passing mode is designed to apply to a slightly different programming scenario. The important difference between out and ref parameters is the definite assignment rules used by each.

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

#4


It's generally frowned upon to use (or abuse) out and ref, often it's much cleaner to return a struct or simple class, containing the multiple fields you need to "return".

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

As for ref vs. out, out requires an un-initialized variable, and the code will not compile unless you set the out param before exiting the function.

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

The code below will therefore not compile:

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

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

ref's does not require you to set them. Also as Hans mentions you can actually "new" the object of a reference type when using ref (since you get a reference to the reference, which is roughly equal to a object** pointer in C++)

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

#5


Really there are 3 ways to pass a parameter to a method: by reference, by value and as output.

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

By value is the default and doesn't have a keyword in C# (it does in VB.Net: ByVal) - it passes a copy of value types:

按值是默认值,并且在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

Confusingly - By value passes a copy of the reference for reference types. That means that your changes to a reference type point back to the instance, but you only have a copy of the actual pointer to the reference:

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

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"

Ok, so now by reference (ref in C# or ByRef in VB.Net) passes a reference to the value for structs:

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

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

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

Simple enough, but for reference types by reference passes the actual pointer to the instance, not a copy:

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

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"

So while both by reference and by value are similar for reference types, the behaviour is very distinct if you are changing the reference itself (rather than what you're referring to).

因此,虽然引用和值的引用类型都相似,但如果您要更改引用本身(而不是您所指的引用),则行为非常不同。

Finally as output is an extra return variable, just like the actual return. These two are bascially the same:

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

public int SomeMethod1() 
{
    return 1;
}

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

If you have an out parameter it must be populated by the method (just like a return).

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