【问题标题】:Why does the .Net framework guidelines recommend that you don't use ref/out arguments?为什么 .Net 框架指南建议您不要使用 ref/out 参数?
【发布时间】:2008-10-18 06:41:43
【问题描述】:

显然,它们“令人困惑”。这是认真的原因吗?你能想到其他人吗?

【问题讨论】:

    标签: c# .net parameters function


    【解决方案1】:

    你见过有多少开发者并不真正了解 ref/out?

    我会在真正需要的地方使用它们,但不会在其他地方使用。它们通常仅在您想有效地返回两个或更多值时才有用 - 在这种情况下,至少值得考虑 是否有一种方法可以使该方法只做一件事。有时使用 ref/out 最合适的方法 - 各种 TryParse 方法等。

    【讨论】:

    • 阿门。几年前我参加了一个 C# 培训课程,小组中有一群“开发人员”无法理解 ref/out。
    • 我猜那群“开发者”从来都不需要理解指针是什么。
    • 我主要使用 ref/out 来提高性能;以每秒 105840000 次的速度复制 256 字节结构是不可能的;)
    • 为什么一开始就有一个 256 字节的结构?
    • 这是一个包含四个 4x4 矩阵的容器。
    【解决方案2】:

    在我看来,它们被认为是代码异味,因为通常有一个更好的选择:返回一个对象。

    如果您注意到,在 .NET 库中,它们仅用于某些特殊情况,即 tryparse 类似的场景,其中:

    • 返回一个类意味着装箱一个值类型
    • 该方法的合同要求它要快,因此装箱/拆箱不是一个可行的选择。

    【讨论】:

      【解决方案3】:

      ref/out 自动意味着可变性,而具有不可变值的函数式编程如今风靡一时。尝试将对 Dictionary.TryGetValue 的调用插入到 LINQ 查询中。 API 需要声明变量并破坏 API 中的任何“流畅性”。

      这并不是说这是“原因”,而是“原因”的一个例子。

      (另见

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

      关于函数式语言如何处理此类 API 的评论。)

      【讨论】:

      • ref/out 意味着变量的可变性,但不一定是数据类型。 (例如,我通常将它与局部变量一起使用。)流畅性很有趣 - TryXXX 往往需要针对不同分支的不同行为,而流畅性并不真正符合 :(
      【解决方案4】:

      困惑可能是最好的理由。混淆意味着降低可维护性并增加引入细微错误的可能性。我以与“goto”控制流语句类似的方式看待它们。虽然它本身并不是坏事,但在过去的几十年里,它导致了许多无法阅读/理解的程序。

      远离任何可能使您的代码更加混乱的事情。

      话虽如此,这些关键字的存在可能是因为框架开发人员看到了对这些东西的需求。如果没有合适的解决方法,请使用它们,但尽可能避免使用它们。

      【讨论】:

        【解决方案5】:

        ref/out 也不适用于“Func”委托,因此这些样式 API 与其他一些使用委托的 API 的组合/重用性较差。

        【讨论】:

          【解决方案6】:

          只是一个想法,当参数捕获目标方法中的执行状态而不是捕获返回的数据时,我发现 ref/out 很有用。考虑一个场景,当您希望从返回 Customer 对象的服务中获取错误消息时。

          Customer GetCustomerById(int id, out string errorMessage);
          

          如果此方法失败,您可能会返回 null Customer 对象或抛出异常。但是,如果我想知道错误的原因(验证?数据库?),我会使用 out 参数。这里的errorMessage参数与数据无关,只是用来捕捉方法执行的问题。

          就我个人而言,如果我有一个预计会返回两个或更多基本数据/值的方法,我会重新考虑我的代码设计。

          【讨论】:

            【解决方案7】:

            我被告知的原因是 1.0 GC 在使用 ref/out 时出现了问题。 2.0(也可能不是 1.1)中的 GC 没有这些问题,所以我通常认为它现在是无用的遗留物。

            【讨论】:

              【解决方案8】:

              @TraumaPony 如果您向我们提供此 .NET 框架指南的来源(URL 或其他内容),那将是很好的。

              【讨论】:

              【解决方案9】:

              您应该返回对象可能是他们建议不使用 ref 或 out 的最可能原因。

              “ref”实际上只需要在传递标量值时使用,但我看到人们经常将它用于通过引用传递的对象。

              【讨论】:

                【解决方案10】:

                代码复杂性的原因还不够吗?比较:

                int myValue;
                ReadFromSomewhere(ref myValue);
                

                收件人:

                int myValue = ReadFromSomewhere();
                

                【讨论】:

                • 当你想要返回 2 个值时怎么样。使用 byref 参数返回 2 个值通常更容易,然后创建一个仅用于调用单个函数的单一目的的对象/结构。
                • 没错,但我指的不是多个参数。大多数时候,如果我是该函数的用户,我会更喜欢结构体。
                • 在基本级别上,这只是因为 2 行而不是 1 行。在多个返回值的情况下,返回信息的方式完全不同。你见过 ruby​​ 风格的多重返回值吗? def GetCoordinates() return 0, 20 end x, y = GetCoordinates();
                • 您的两个示例不等效:您的意思是“out”而不是“ref”。这会影响编译器错误和流控制分析。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-02-25
                • 2010-11-03
                • 2011-02-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多