最佳实践:函数返回值或byref输出参数?

时间:2008-10-29 13:39:24

标签: function return-value return

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

是最好的方法:

  1. 编写一个函数,如果找不到则返回false,如果找到则返回true,找到的行号作为byref / output参数,或者
  2. 编写一个返回int的函数,如果找不到行值则返回-999,如果是行号,则返回行号?

8 个答案:

答案 0 :(得分:13)

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

我会改为制作两种方法:

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));
}

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

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

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

理查德哈里森是正确的,命名常量优于裸-1或-999。

答案 4 :(得分:1)

我会选择2或其他一些变量,其中返回值表示是否找到了值。

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

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

答案 5 :(得分:1)

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

BTW -1更可接受,并且比#999更广泛地使用“幻数”,这是它“正确”的唯一原因(由于某种原因使用了引号)。

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

答案 6 :(得分:0)

在这种情况下,该项目可能不在那里,这是一个好的条件。这是GridView中未选定值绑定到数据表的错误陷阱。

答案 7 :(得分:0)

尚未提及的另外几种可能性:

// Method 1: Supports covariance; can return default<T> on failure.
T TryGetThing(ref bool success); 

// Method 2: Does not support covariance, but may allow cleaner code in some cases
// where calling code would use some particular value in in case of failure.
T TryGetThing(T DefaultValue);

// Method 3: Does not support covariance, but may allow cleaner code in some cases
// where calling code would use some particular value in case of failure, but should
// not take the time to compute that value except when necessary.
T TryGetThing(Func<T> AlternateGetMethod);

// Method 4: Does support covariance; ErrorMethod can throw if that's what should
// happen, or it can set some flag which is visible to the caller in some other way.
T TryGetThing(Action ErrorMethod);

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