【问题标题】:Best Practice: function return value or byref output parameters?最佳实践:函数返回值还是 byref 输出参数?
【发布时间】:2008-10-29 13:39:23
【问题描述】:

我有一个名为 FindSpecificRowValue 的函数,它接收数据表并返回包含特定值的行号。如果找不到该值,我想向调用函数表明这一点。

是最好的方法:

  1. 编写一个函数,如果未找到则返回 false,如果找到则返回 true,并将找到的行号作为 byref/输出参数,或者
  2. 编写一个函数,如果没有找到行值,则返回 int 并返回 -999,如果找到则返回行号?

【问题讨论】:

    标签: function return-value return


    【解决方案1】:

    我个人不会使用该方法名称。

    我会改用两种方法:

    TryFindSpecificRow
    FindSpecificRow
    

    这将遵循 Int32.Parse/TryParse 的模式,在 C# 中它们可能如下所示:

    public static Boolean TryFindSpecificRow(DataTable table, out Int32 rowNumber)
    {
        if (row-can-be-found)
        {
            rowNumber = index-of-row-that-was-found;
            return true;
        }
        else
        {
            rowNumber = 0; // this value will not be used anyway
            return false;
        }
    }
    
    public static Int32 FindSpecificRow(DataTable table)
    {
        Int32 rowNumber;
    
    
        if (TryFindSpecificRow(table, out rowNumber))
            return rowNumber;
        else
            throw new RowNotFoundException(String.Format("Row {0} was not found", rowNumber));
    }
    

    编辑:更改为更适合问题。

    【讨论】:

    • 这是一个不错的方法,尤其是使用熟悉的 TryParse 语法
    • 真的需要2个函数吗?为什么不在 FindSpecificRow 中查找 rowNumber,如果 !row-can-be-found 则抛出异常。
    • 嗯,这取决于。如果预计该函数在几乎所有情况下都能成功,我只会实现一个 FindSpecificRow,如果由于某种奇怪的原因它最终找不到该行,则会引发异常。但是,如果我希望请求有时会失败,或者换句话说,如果我希望调用代码有时想要给我打电话并期待一个否定的结果,我会同时实现它们。不抛出异常比这样做更便宜。
    • @Junier 有时程序员需要第一个选项,有时需要第二个选项。为了避免重复代码,可以做的是让一个函数像主要答案一样调用另一个函数
    【解决方案2】:

    失败的函数应该抛出异常。

    如果失败是预期流程的一部分,则返回带外值是可以的,除非您无法预先确定带外值是什么,在这种情况下您必须抛出异常。

    如果我必须在您的选项之间进行选择,我会选择选项 2,但使用常量而不是 -999...

    【讨论】:

    • 呃-哦 - 异常行为战争即将来临... 为掩护而潜水
    【解决方案3】:

    您还可以将返回值定义为Nullable,如果没有找到,则返回 Nothing。

    【讨论】:

      【解决方案4】:

      我会选择选项 2。虽然我认为我只会使用 -1 而不是 -999。

      Richard Harrison 说得对,命名常量比纯 -1 或 -999 更好。

      【讨论】:

        【解决方案5】:

        我会选择 2,或者返回值指示是否找到值的其他变体。

        函数返回(或提供引用)的行的值似乎已经表明是否找到了该值。如果未找到值,则提供不包含该值的行号似乎没有意义,因此返回值应为 -1、Null 或任何其他适用于特定语言的值。否则,返回行号这一事实表明已找到该值。

        因此,似乎不需要单独的返回值来指示是否找到了该值。但是,如果类型 1 符合特定语言的习语以及其中执行函数调用的方式,则它可能是合适的。

        【讨论】:

          【解决方案6】:

          使用 2)但返回 -1(如果返回对行的引用,则返回空引用),该习语被广泛使用(包括通过 .nets indexOf (item) 函数),这就是我可能会做的.

          顺便说一句,-1 比 -999 更容易接受和广泛使用“幻数”,这就是它“正确”的唯一原因(此处使用引号是有原因的)。

          然而,这在很大程度上与您的期望有关。项目是否应该一直在那里,但您只是不知道在哪里?在这种情况下,正常返回索引,如果不存在则抛出错误/异常。

          【讨论】:

            【解决方案7】:

            在这种情况下,该项目可能不存在,这是正常的情况。这是绑定到数据表的 GridView 中未选择值的错误陷阱。

            【讨论】:

              【解决方案8】:

              尚未提及的其他几种可能性:

              // 方法一:支持协方差;失败时可以返回 default。 T TryGetThing(ref bool 成功); // 方法2:不支持协方差,但在某些情况下可能允许更简洁的代码 // 如果失败,调用代码将使用一些特定的值。 T TryGetThing(T DefaultValue); // 方法3:不支持协方差,但在某些情况下可能允许更简洁的代码 // 如果失败,调用代码将使用一些特定的值,但应该 // 除非必要,否则不花时间计算该值。 T TryGetThing(Func AlternateGetMethod); // 方法四:是否支持协方差;如果这是应该的,ErrorMethod 可以抛出 // 发生,或者它可以设置一些其他方式对调用者可见的标志。 T TryGetThing(操作错误方法);

              第一种方法与 Microsoft 在支持协变接口之前开发的方法相反。最后一个在某些方面是最通用的,但可能需要在每次使用时创建几个新的 GC 对象实例(例如闭包和委托)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-07-23
                • 1970-01-01
                • 2016-07-03
                • 1970-01-01
                • 2021-11-14
                • 2015-10-09
                相关资源
                最近更新 更多