简体   繁体   English

为什么.Net框架指南建议您不要使用ref / out参数?

[英]Why does the .Net framework guidelines recommend that you don't use ref/out arguments?

Apparently, they're "confusing". 显然,他们“令人困惑”。 Is that seriously the reason? 那是认真的原因吗? Can you think of any others? 你能想到其他人吗?

Have you seen how many developers don't really understand ref/out? 您是否看到有多少开发人员不了解ref / out?

I use them where they're really necessary, but not otherwise. 我在他们真正需要的地方使用它们,但不是这样。 They're usually only useful if you want to effectively return two or more values - in which case it's worth at least thinking about whether there's a way of making the method only do one thing instead. 它们通常只有在您想要有效地返回两个或更多值时才有用 - 在这种情况下,至少值得考虑是否有一种方法可以使该方法只做一件事。 Sometimes using ref/out is the most appropriate approach - the various TryParse methods etc. 有时使用ref / out 最合适的方法 - 各种TryParse方法等。

In my opinion, they are considered a code smell because in general there is a much better option: returning an object. 在我看来,它们被认为是代码气味,因为通常有一个更好的选择:返回一个对象。

If you notice, in the .NET library they are only used in some special cases, namely tryparse -like scenarios where: 如果您注意到,在.NET库中它们仅用于某些特殊情况,即类似于tryparse的场景,其中:

  • returning a class would mean boxing a value type 返回一个类意味着装箱值类型
  • the contract of the method requires it to be fast, and so boxing/unboxing is not a viable option. 该方法的合同要求它快,因此装箱/拆箱不是一个可行的选择。

ref/out automatically means mutability, and functional programming with immutable values is all the rage these days. ref / out自动意味着可变性,而且使用不可变值的函数式编程最近风靡一时。 Try inserting a call to Dictionary.TryGetValue into a LINQ query. 尝试将对Dictionary.TryGetValue的调用插入LINQ查询。 The API requires declaring variables and ruins any 'fluency' in the API. API需要声明变量并破坏API中的任何“流畅性”。

That's not to say this is "the reason", but it is an example of "a reason". 这并不是说这是“原因”,而是一个“理由”的例子。

(See also (也可以看看

http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!181.entry http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!181.entry

for commentary on how functional languages deal with such APIs.) 关于功能语言如何处理这些API的评论。)

Confusing is probably the best reason. 令人困惑的可能是最好的理由。 Confusing means decreased maintainability and increased likelyhood on introducing subtle bugs. 混乱意味着可维护性降低,并且在引入细微错误方面可能性增加。 I see them in a similar view to the "goto" control flow statement. 我在与“goto”控制流程语句类似的视图中看到它们。 While it is not inherently bad on its own accord, it has lead to many many impossible to read / understand programs over the decades. 虽然它本身并不是坏事,但它导致许多人在几十年内无法阅读/理解程序。

Stay away from anything that can make your code more confusing then it needs to be. 远离任何可能使您的代码更加混乱的事情。

Having said that, those keywords exist probably because the framework developers saw need for such things. 话虽如此,这些关键字的存在可能是因为框架开发人员认为需要这样的东西。 Use them if there is no suitable workaround, but avoid them when you can. 如果没有合适的解决方法,请使用它们,但尽可能避免使用它们。

ref / out也不能与“Func”委托一起使用,因此这些样式API与使用委托的一些其他API不太可组合/可重用。

Just a thought, I find ref/out to be useful when the arguments capture the state of execution in target method rather than capturing returned data. 只是一个想法,当参数捕获目标方法中的执行状态而不是捕获返回的数据时,我发现ref / out有用。 Consider a scenario when you want to get an error message from a service that returns Customer object. 当您想要从返回Customer对象的服务获取错误消息时,请考虑这种情况。

Customer GetCustomerById(int id, out string errorMessage);

If this method fails, you would probably return null Customer object or throw an exception. 如果此方法失败,您可能会返回null Customer对象或抛出异常。 However, if I want to know the cause of error (validation? database?), I would use out argument. 但是,如果我想知道错误的原因(验证?数据库?),我会用掉参数。 errorMessage argument here has nothing to do with data, simply used to capture what's wrong with the method execution. 这里的errorMessage参数与数据无关,只是用于捕获方法执行的错误。

Personally if I have a method that is expected to return two or more essential data/values, I would rethink the design of my code. 就个人而言,如果我有一个预期返回两个或更多基本数据/值的方法,我会重新考虑我的代码的设计。

The reason I was told is the 1.0 GC had problems when ref/out was used. 我被告知的原因是1.0 GC在使用ref / out时出现问题。 The GC in 2.0 (and probably not 1.1 either) doesn't have those problems so I would normally assume it is a now non-useful legacy. 2.0中的GC(也可能不是1.1)没有那些问题所以我通常认为它是一个现在没有用的遗产。

@TraumaPony如果您向我们提供此.NET框架指南的源(URL或其他内容),那就没问题了。

You should be returning objects is probably the most likely reason that they suggest not using ref or out. 您应该返回对象可能是他们建议不使用ref或out的最可能原因。

"ref" really only needs to be used when passing scalar values but I see people use it often for objects that are being passed by reference anyways. “ref”实际上只需要在传递标量值时使用,但我看到人们常常将它用于通过引用传递的对象。

Isn't code complexity reason enough? 代码复杂性的原因不够吗? Compare: 相比:

int myValue;
ReadFromSomewhere(ref myValue);

To: 至:

int myValue = ReadFromSomewhere();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM