什么情况下是“out”?参数有用(不能使用“ref”来代替)?

发布于 2024-09-06 20:47:50 字数 155 浏览 4 评论 0原文

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

那么是否还有其他情况下 out 参数可能有用,而我们不能使用 ref 参数呢?

谢谢。

As far as I can tell, the only use for out parameters is that a caller can obtain multiple return values from a single method invocation. But we can also obtain multiple result values using ref parameters instead!

So are there other situations where out parameters could prove useful and where we couldn't use ref parameters instead?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

傾城如夢未必闌珊 2024-09-13 20:47:50

是的 - refout 之间的区别在于明确赋值:

  • 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);

在这种情况下,okvalue将隐式键入为boolint 分别。这样就可以清楚地知道方法中的内容(text)和输出的内容(两条信息:okvalue)。

如果 int.TryParse 使用 ref 参数,那么这根本不可用 - 因为编译器无法知道它是否会实际上关心关于ref参数的初始值。

Yes - the difference between ref and out is in terms of definite assignment:

  • An out parameter doesn't have to be definitely assigned by the caller before the method call. It does have to be definitely assigned in the method before it returns normally (i.e. without an exception). The variable is then definitely assigned in the caller after the call.

  • A ref parameter does have to be definitely assigned by the caller before the method call. It doesn't have to be assigned a different value in the method.

So suppose we wanted to change int.TryParse(string, out int) to use ref instead. Usually the calling code looks like this:

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

Now if we used ref, we'd have to give value a value before the call, e.g.:

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

Obviously it's not a huge difference - but it gives the wrong impression. We're assigning a value that we have no intention of ever using, and that's not a good thing for readability. An out parameter indicates that a value will come out of the method (assuming there's no exception) and that you don't need to have a value to start with.

Once of the suggestions I've made for C# 5 (I've no idea if it'll be taken up or not) is that a method with an out parameter should be able to regarded as a method returning a tuple of values. Combined with better support for tuples, that would mean we could do something like this:

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

In this case ok and value would be implicitly typed to bool and int respectively. That way it's clear what's going into the method (text) and what's coming out (two pieces of information: ok and value).

That would simply not be available if int.TryParse used a ref parameter instead - as the compiler can't know whether it's going to actually care about the initial value of the ref parameter.

不弃不离 2024-09-13 20:47:50

您可以这样看待参数:

  • 普通参数参数中:
    值可以通过这样的参数进入函数;

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

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

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

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

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

You can look at parameters in this way:

  • normal parameters are in parameters:
    A value can go into the function through such a parameter; therefore it must be initialized.

  • ref parameters are in-out parameters:
    A value can go into and out of a function through such a parameter. Because of the former, it must also be initialized.

  • out parameters are out parameters:
    A value is only supposed to come back from a function through such a parameter; therefore, it doesn't need to be initialized.

I came up with this way of looking at ref/out parameters by studying Microsoft's COM technology. IDL (interface description language) is used to describe COM component interfaces, and with IDL, parameters are augmented with in, out, and inout declarators. I suspect .NET and C# have partly inherited these declarators from COM, albeit with slightly different names (ref instead of inout).

With COM, out parameters are frequently used to retrieve an interface method's actual return value, since the "real" return value is often already used for returning a HRESULT success/error code.

With .NET, I think out parameters have far less importance, even in cases where you want to return several values from a method (you could return complex objects or Tuples in these situations).

流心雨 2024-09-13 20:47:50

一个重要的区别是:

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

(ref 参数不需要此)

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

One important difference is this:

A variable passed as an out argument
need not be initialized. However, the
out parameter must be assigned a value
before the method returns.

(A ref parameter does not require this)

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

ι不睡觉的鱼゛ 2024-09-13 20:47:50

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

An out parameter is useful when you want multiple result values from a method. Technically, you could use a ref parameter to achieve the same goal but an out parameter does a significantly better job at conveying intent. When you use ref, It is not clear why you are doing so instead of using out or instead of using the function result. Presumably, you intend on changing the value passed, but why you are changing it isn't clear simply from the function signature.

青巷忧颜 2024-09-13 20:47:50

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

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

out 优于 ref 的主要原因是您不需要分配虚拟值在调用之前将值赋给 return var(甚至是隐式的)。

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

I think a fine example is int.TryParse()

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

The primary reason that out is better than ref is that you don't need to assign a dummy value to the return var before calling (even implicitly).

So out tells you, and the compiler: "This var will be assigned within the method. And the var's initial value, if any, will not even be looked at."

若沐 2024-09-13 20:47:50

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

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

Major difference between the two is that if we are using ref then we have to initialize this before call and it is optional that we assign a value to our ref variable in our method.

However for out methods we do not have to explicitly initialize them but in our method we have to assign some value to it, otherwise they will generate compile time error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文