显然,它们“令人困惑”。这是认真的原因吗?你能想到其他人吗?
10 回答
你见过有多少开发者并不真正了解 ref/out 吗?
我在真正需要的地方使用它们,但不是在其他地方使用它们。它们通常仅在您想有效地返回两个或多个值时才有用 - 在这种情况下,至少值得考虑是否有一种方法可以使该方法只做一件事。有时使用 ref/out是最合适的方法 - 各种 TryParse 方法等。
在我看来,它们被认为是代码异味,因为通常有一个更好的选择:返回一个对象。
如果您注意到,在 .NET 库中,它们仅在某些特殊情况下使用,即类似 tryparse的场景:
- 返回一个类意味着装箱一个值类型
- 该方法的合同要求它快速,因此装箱/拆箱不是一个可行的选择。
ref/out 自动意味着可变性,而具有不可变值的函数式编程如今风靡一时。尝试将对 Dictionary.TryGetValue 的调用插入到 LINQ 查询中。API 需要声明变量并破坏 API 中的任何“流畅性”。
这并不是说这是“原因”,而是“原因”的一个例子。
(也可以看看
http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!181.entry
有关函数式语言如何处理此类 API 的评论。)
困惑可能是最好的理由。混淆意味着降低可维护性并增加引入细微错误的可能性。我以与“goto”控制流语句类似的方式看待它们。虽然它本身并不是坏事,但在过去的几十年里,它导致了许多无法阅读/理解的程序。
远离任何可能使您的代码更加混乱的事情。
话虽如此,这些关键字的存在可能是因为框架开发人员看到了对这些东西的需求。如果没有合适的解决方法,请使用它们,但尽可能避免使用它们。
ref/out 也不适用于“Func”委托,因此这些样式 API 与其他一些使用委托的 API 的组合/重用性较差。
只是一个想法,当参数捕获目标方法中的执行状态而不是捕获返回的数据时,我发现 ref/out 很有用。当您希望从返回客户对象的服务中获取错误消息时,请考虑一个场景。
Customer GetCustomerById(int id, out string errorMessage);
如果此方法失败,您可能会返回 null Customer 对象或引发异常。但是,如果我想知道错误的原因(验证?数据库?),我会使用 out 参数。这里的errorMessage参数与数据无关,只是用来捕捉方法执行的问题。
就个人而言,如果我有一个方法可以返回两个或更多基本数据/值,我会重新考虑我的代码设计。
我被告知的原因是 1.0 GC 在使用 ref/out 时出现问题。2.0(也可能不是 1.1)中的 GC 没有这些问题,所以我通常认为它现在是无用的遗产。
@TraumaPony 如果您向我们提供此 .NET 框架指南的来源(URL 或其他内容),那就太好了。
您应该返回对象可能是他们建议不使用 ref 或 out 的最可能原因。
“ref”实际上只需要在传递标量值时使用,但我看到人们经常将它用于通过引用传递的对象。
代码复杂性的理由还不够吗?比较:
int myValue;
ReadFromSomewhere(ref myValue);
到:
int myValue = ReadFromSomewhere();