18

据我所知,out参数的唯一用途是调用者可以从单个方法调用中获取多个返回值。但是我们也可以使用ref参数来获取多个结果值!

那么在其他情况下,out参数可以证明是有用的,而我们不能使用ref参数来代替吗?

谢谢你。

4

6 回答 6

29

ref是的 -和之间的区别在于out明确的分配:

  • 调用者不必在方法调用之前明确分配out参数。在它正常返回之前,它确实必须在方法中明确分配(即没有例外)。然后在调用后明确地在调用者中分配该变量。

  • 在方法调用之前,调用者必须明确地分配参数ref不必在方法中为其分配不同的值。

所以假设我们想改为int.TryParse(string, out int)使用ref。通常调用代码如下所示:

int value;
if (int.TryParse(text, out value))
{
    // Use value
}
else
{
    // Do something else
}

现在如果我们使用ref,我们必须value在调用之前给出一个值,例如:

int value = 0;
if (int.TryParse(text, ref value))
{
    // Use value
}
else
{
    // Do something else
}

显然这不是一个巨大的差异 - 但它给人的印象是错误的。我们正在分配一个我们无意使用的值,这对可读性来说不是一件好事。out参数表示方法产生一个值(假设没有例外),并且您不需要从一个值开始。

我为 C# 5 提出的建议之一(我不知道它是否会被采用)是带有out参数的方法应该能够被视为返回值元组的方法。结合对元组的更好支持,这意味着我们可以做这样的事情:

var (ok, value) = int.TryParse(text);

在这种情况下ok, andvalue将分别隐式键入到boolinttext这样一来,方法 ( ) 中的内容和输出的内容(两条信息:ok和)就很清楚了value

int.TryParse如果改为使用参数,那将根本不可用ref- 因为编译器无法知道它是否会真正关心ref参数的初始值。

于 2010-06-27T19:02:25.260 回答
8

可以这样查看参数:

  • 普通参数参数中:
    一个值可以通过这样的参数进入函数;因此它必须被初始化。

  • ref参数是in-out参数:
    一个值可以通过这样的参数进出函数。由于前者,它也必须被初始化。

  • out参数是输出参数:
    一个值只能通过这样的参数从函数中返回;因此,它不需要初始化。

我通过研究微软的 COM 技术想出了这种查看ref/参数的方式。outIDL(接口描述语言)用于描述 COM 组件接口,使用 IDL,参数增加了in, out, 和inout声明符。我怀疑 .NET 和 C# 已经从 COM 部分继承了这些声明符,尽管名称略有不同(ref而不是inout)。

对于 COM,out参数经常用于检索接口方法的实际返回值,因为“真实”返回值通常已经用于返回HRESULT成功/错误代码。

对于 .NET,我认为out参数的重要性要小得多,即使在您想从一个方法返回多个值的情况下(Tuple在这些情况下您可以返回复杂的对象或 s)。

于 2010-06-27T19:18:51.290 回答
4

一个重要的区别是:

作为输出参数传递的变量不需要初始化。但是,必须在方法返回之前为 out 参数赋值。

(一个 ref 参数不需要这个)

来源: http: //msdn.microsoft.com/en-us/library/t3c3bfhx (VS.71).aspx

于 2010-06-27T19:03:59.313 回答
2

当您需要一个out方法的多个结果值时,参数很有用。从技术上讲,您可以使用ref参数来实现相同的目标,但out参数在传达意图方面做得更好。当您使用ref时,不清楚为什么要这样做而不是使用out或代替使用函数结果。据推测,您打算更改传递的值,但是仅仅从函数签名中就不清楚为什么要更改它。

于 2010-06-27T19:08:31.357 回答
2

我认为一个很好的例子是 int.TryParse()

http://msdn.microsoft.com/en-us/library/f02979c7.aspx

outref更好的主要原因是您不需要在调用之前(甚至是隐式地)为 return var 分配一个虚拟值。

所以out告诉你,编译器:“这个 var 将在方法内分配。并且 var 的初始值,如果有的话,甚至不会被查看。”

于 2010-06-27T19:43:48.080 回答
0

两者之间的主要区别在于,如果我们使用ref,那么我们必须在调用之前对其进行初始化,并且我们可以在方法中为ref变量赋值。

然而,对于out方法,我们不必显式地初始化它们,但在我们的方法中,我们必须为其分配一些值,否则它们会产生编译时错误。

于 2010-06-28T04:47:03.653 回答