在.NET中,ref
和out
参数有什么区别?它们各自更加适用的场景是什么?能否提供一个使用其中一种参数而另一种无法使用的代码片段?
它们基本上是一样的 - 唯一的区别是,你作为 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
),这些数据已经使用返回值进行了某些操作。
out
参数的方法必须初始化它。接收ref
参数的方法可以随意使用它。它可以忽略它。我正在回滚它。 - xanatos一个使用'out'参数的方法的调用者在调用前不需要为传递的变量赋值; 但是,被调用的方法必须在返回前将'out'参数赋值。
相反,'ref'参数被认为是由调用者初始化的。因此,在使用之前,被调用方不需要为'ref'参数赋值。'ref'参数同时被传入和传出方法。
因此,'out'表示输出,而'ref'则表示输入和输出。
这与COM接口的'[out]
'和'[in,out]
'参数密切对应。使用'out'参数的优点在于,调用者在不需要被调用方法使用预分配对象的情况下不需要传递一个 - 这避免了分配的成本以及可能与封送相关的任何成本(在COM中更常见,但在.NET中也很常见)。
ref
和out
都允许被调用的方法修改参数。它们之间的区别在于在进行函数调用之前发生了什么。
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;
}
}
}
希望现在清楚了。Output:
0 10
ref
变量。out
变量需要在函数实现中进行设置。out
参数可以被看作是额外的返回变量(而不是输入)。ref
参数可以被看作是既有输入又有输出的变量。out
和ref
参数用于将返回值保存在与传递给方法的变量相同的变量中。当方法需要返回多个值时,这两个参数非常有用。
必须在调用方法体中为out
参数分配值,否则该方法将无法编译。
< p > Ref参数示例Ref Parameter : It has to be initialized before passing to the Method. The
ref
keyword on a method parameter causes a method to refer to the same variable that was passed as an input parameter for the same method. If you do any changes to the variable, they will be reflected in the variable.
int sampleData = 0; sampleMethod(ref sampleData);
public static void Main()
{
int i = 3; // Variable need to be initialized
sampleMethod(ref i );
}
public static void sampleMethod(ref int sampleData)
{
sampleData++;
}
Out Parameter : It is not necessary to be initialized before passing to Method. The
out
parameter can be used to return the values in the same variable passed as a parameter of the method. Any changes made to the parameter will be reflected in the variable.
int sampleData; sampleMethod(out sampleData);
输出参数示例
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;
}
C#中的方法只能返回一个值。如果您想要返回多个值,可以使用out关键字。out修饰符返回的是引用传递。简单地说,“out”关键字用于从方法获取值。
在C#中,当您将int、float、double等值类型作为参数传递给方法参数时,它是按值传递的。因此,如果您修改参数值,它不会影响方法调用中的参数。但是,如果您使用“ref”关键字标记参数,则会反映在实际变量中。
out
表示该参数是输出参数,即在方法显式设置之前没有值。
ref
指定该值是一个具有值的引用,在方法内部可以更改其值。
Ref参数在函数中不是必须设置的,而out参数必须绑定一个值后才能退出函数。作为out传递的变量也可以在未初始化的情况下传递到函数中。
out
参数是一个带有特殊的 Out()
属性的 ref
参数。如果一个 C# 方法的参数声明为 out
,编译器将要求在读取参数和方法返回之前写入该参数。如果 C# 调用一个包含 Out()
属性参数的方法,编译器将会假装变量在调用方法之前被写入,以决定是否报告 "未定义变量" 错误。请注意,由于其他 .net 语言不附加相同的含义到 Out()
属性上,因此调用具有 out
参数的例程可能会使相关变量不受影响。如果一个变量在被明确赋值之前被用作 out
参数,C# 编译器将生成代码以确保它在使用之前的某个时刻被清除,但如果这样的变量离开并重新进入范围,则不能保证它会再次被清除。