为什么 ref 参数不能像 out 参数一样被忽略?

7

为什么C# 7带来了内联out参数,但却没有ref参数?是否有特定的原因?

以下内容在C# 7上是有效的:

int.TryParse("123", out _);

但这是无效的:
public void Foo(ref int x) { }

Foo(ref _); // error

我认为同样的逻辑也可以应用于 ref 参数。


1
会不会是因为语义不同呢?使用 out 时,你期望得到一个结果;而使用 ref 时,你传递的是一个引用。 - dcg
4
你认为输入时这个参数的值应该是什么?default(T)吗? - Jeroen Mostert
1
ref 表示传递的参数值可以在 Foo 方法中使用;然而 未初始化 的本地变量 - Foo(ref _) - 包含垃圾数据。 - Dmitry Bychenko
1
@SelmanGenç:在你将功能请求发布到Github之前,我只是想让它完整一些。:-P 说实话,我认为这比针对“out”更不实用 - 而且即使从一开始就并不是很热门的功能也不是。有哪些(现实可行的)方法需要使用“ref”参数,而你想完全忽略它们,在传递该特定类型的“默认值”时能够正确工作? - Jeroen Mostert
1
@SelmanGenç 你的方法是否实际上使用了传递给那些ref参数的值?如果没有,为什么要使用ref。在写C#的9年中,我想我可能只用过一次ref。它不是一个非常广泛使用的功能,所以我质疑为什么你有一个需要使用两个ref的方法。 - JLRishe
显示剩余7条评论
1个回答

12

原因很简单:因为你不能将未初始化的变量传递给ref参数。这一直都是这样,C#7中的新语法糖也没有改变这一点。

观察:

int i;
MyOutParameterMethod(out i);  // allowed

int j;
MyRefParameterMethod(ref j);  // compile error

C#7中的新特性允许你在调用带有out参数的方法时创建一个变量。它不改变未初始化变量的规则。 ref参数的目的是允许将已初始化的值传递到方法中,并(可选地)允许更改原始变量。方法体内的编译器语义将ref参数视为已初始化变量,将out参数视为未初始化变量。在C#7中保持不变。


2
虽然准确,但这并不是重点。初始化为默认值本来是完全合理的。考虑一个名为 Thingie MakeThingie ( ref string locationWhereToPutThingie ) 的函数,它使用预定义的位置,除非提供了其他位置。Thingies 对它们的位置并不关心,因此位置不应该成为它们的一部分,调用者有时也可能不关心位置。MakeThingie ( ref _ ) 看起来很容易。 - chase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接