.NET中ref和out参数的区别

.NET中refout参数的区别是什么?在什么情况下,一个会比另一个更有用?一个可以使用而另一个不能使用的代码片段是什么?

269777 次浏览

Ref可能会在null时阻塞,因为它可能期望修改一个现有对象。Out需要null,因为它返回一个新对象。

在函数中不需要设置Ref形参,而out形参必须在退出函数之前绑定到一个值。传递出去的变量也可以在没有初始化的情况下传递给函数。

out参数由被调用的方法初始化,ref参数在调用方法之前初始化。因此,当你只需要获得第二个返回值时,out参数被使用,ref参数被用于获得一个值而且,可能会返回对该值的更改(次于主返回值)。

它们几乎是一样的——唯一的区别是,作为out参数传递的变量不需要初始化,但作为ref参数传递的变量必须设置为某个值。

int x;
Foo(out x); // OK


int y;
Foo(ref y); // Error: y should be initialized before calling the method

Ref参数用于可能被修改的数据,out参数用于已经使用返回值的函数(例如int.TryParse)的额外输出数据。

ref关键字用于通过引用传递值。(这并不排除传递的值是值类型或引用类型)。用out关键字指定的输出参数用于从方法返回值。

代码中的一个关键区别是必须在方法中设置输出参数的值。对于ref参数则不是这样。

有关更多细节,请参阅http://www.blackwasp.co.uk/CSharpMethodParameters.aspx

这个 c#中的out和ref参数有一些很好的例子。

基本的区别是out参数在传入时不需要初始化,而ref参数需要初始化。

Out和ref是完全相同的,除了Out变量在发送到深渊之前不需要初始化。我没有那么聪明,我从MSDN库抄袭了:)。

然而,更明确地说,修饰符的含义是,如果您在代码中更改了该变量的引用,out和ref将导致调用变量也更改引用。在下面的代码中,一旦newGuy从doStuff调用中返回,ceo变量将是它的引用。如果不是为了ref(或out),引用就不会被改变。

private void newEmployee()
{
Person ceo = Person.FindCEO();
doStuff(ref ceo);
}


private void doStuff(ref Person employee)
{
Person newGuy = new Person();
employee = newGuy;
}

refout都允许被调用的方法修改形参。它们之间的区别是发生了什么之前你做的调用。

  • ref表示参数上有一个值之前进入函数。被调用的函数可以在任何时候读取或更改值。参数输入,然后输出

  • out表示参数在进入函数之前没有正式值。被调用的函数必须初始化它。参数只输出

下面是我最喜欢的看待它的方式:ref是通过引用传递变量。out是为函数声明第二个返回值。就像你可以这样写:

// This is not C#
public (bool, string) GetWebThing(string name, ref Buffer paramBuffer);


// This is C#
public bool GetWebThing(string name, ref Buffer paramBuffer, out string actualUrl);

以下是每种替代方法的更详细的效果列表:

在调用方法之前:

ref:调用方必须在将参数传递给被调用方法之前设置参数的值。

out:调用方方法在调用方法之前不需要设置实参的值。很可能,你不应该这么做。事实上,任何当前值都将被丢弃。

通话过程中:

ref:被调用的方法可以在任何时候读取参数。

out:被调用的方法必须在读取参数之前初始化它。

远程调用:

ref:当前值被编组到远程调用。额外的性能成本。

out:没有任何东西被传递给远程调用。得更快。

从技术上讲,你可以总是使用ref来代替out,但out可以让你更精确地确定参数的含义,有时它可以更有效。

OUT的例子:变量在进入方法后得到初始化的值。稍后将相同的值返回给主方法。

namespace outreftry
{
class outref
{
static void Main(string[] args)
{
yyy a = new yyy(); ;


// u can try giving int i=100 but is useless as that value is not passed into
// the method. Only variable goes into the method and gets changed its
// value and comes out.
int i;


a.abc(out i);


System.Console.WriteLine(i);
}
}
class yyy
{


public void abc(out int i)
{


i = 10;


}


}
}

输出:

10

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

例如:变量应该在进入方法之前初始化。稍后相同的值或修改后的值将返回给主方法。

namespace outreftry
{
class outref
{
static void Main(string[] args)
{
yyy a = new yyy(); ;


int i = 0;


a.abc(ref i);


System.Console.WriteLine(i);
}
}
class yyy
{


public void abc(ref int i)
{
System.Console.WriteLine(i);
i = 10;


}


}
}

输出:

    0
10

=================================

希望现在晴了。

  • ref变量需要在传入之前进行初始化。
  • out变量需要在函数实现中设置
  • out参数可以被认为是额外的返回变量(不是输入)
  • ref参数可以被认为是输入和输出变量。

out指定参数是一个输出参数,也就是说,在方法显式设置它之前,它没有值。

ref指定该值是一个具有值的引用,并且您可以在方法中更改其值。

Ref和Out参数:

outref参数用于返回相同变量中的值,您可以将其作为方法的参数传递。当您的方法需要返回多个值时,这两个参数非常有用。

必须在calee方法体中为out参数赋值,否则该方法将无法编译。


参考参数:必须在传递给方法之前进行初始化。 方法参数上的ref关键字会导致方法引用作为同一方法输入参数传递的相同变量。如果您对变量做了任何更改,这些更改将反映在变量中。< / p >
int sampleData = 0;
sampleMethod(ref sampleData);

Ex of Ref Parameter . /em>

public static void Main()
{
int i = 3; // Variable need to be initialized
sampleMethod(ref i );
}


public static void sampleMethod(ref int sampleData)
{
sampleData++;
}

输出参数:在传递给Method之前不需要初始化。 out参数可用于返回作为方法参数传递的同一变量中的值。对参数所做的任何更改都将反映在变量中

 int sampleData;
sampleMethod(out sampleData);

Out参数的Ex < / >强

public static void Main()
{
int i, j; // Variable need not be initialized
sampleMethod(out i, out j);
}
public static int sampleMethod(out int sampleData1, out int sampleData2)
{
sampleData1 = 10;
sampleData2 = 20;
return 0;
}

out形参是一个带有特殊Out()属性的ref形参。如果c#方法的形参声明为out,编译器将要求在读取形参和方法返回之前先写入形参。如果c#调用一个参数包含Out()属性的方法,为了决定是否报告“未定义变量”错误,编译器会假装在调用方法之前立即写入该变量。请注意,由于其他。net语言没有为Out()属性附加相同的含义,因此调用带有out参数的例程可能不会影响所讨论的变量。如果一个变量在被明确赋值之前被用作out形参,c#编译器将生成代码,以确保它在被使用之前的某个时刻被清除,但如果这样的变量离开并重新进入作用域,则不能保证它将再次被清除。

:

在c#中,一个方法只能返回一个值。如果希望返回多个值,可以使用out关键字。out修饰符返回为引用返回。最简单的答案是使用关键字“out”从方法中获取值。

  • 您不需要在调用函数中初始化该值。
  • 必须在被调用的函数中赋值,否则编译器将报错。

裁判:

在c#中,当你将一个值类型,如int, float, double等作为参数传递给方法参数时,它是按值传递的。因此,如果修改形参值,它不会影响方法调用中的实参。但是,如果您用“ref”关键字标记参数,它将反映在实际的变量中。

  • 在调用函数之前,需要初始化变量。
  • 为方法中的ref参数赋值不是强制的。如果不更改值,为什么需要将其标记为“ref”?

它们有微妙的不同。

out形参在传递给方法之前不需要由被调用方初始化。因此,任何带有out形参的方法

  • 在为参数赋值之前无法读取该参数
  • 必须在返回之前给它赋值吗

这用于需要覆盖其参数的方法,而不管其先前的值如何。


ref形参在传递给方法之前必须由被调用方初始化。因此,任何带有ref形参的方法

  • 在赋值之前可以检查值吗
  • 可以返回原值,不受影响吗

这用于必须检查其值并对其进行验证或规范化的方法。

out在c# 7中获得了一个新的更简洁的语法 https://learn.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7#more-expression-bodied-members 更令人兴奋的是c# 7的元组增强,这是一个比使用ref和out更优雅的选择