7

我可以想到以下从一个方法返回多个值的方法(一种分为两种方法)

private bool IsCarFaulty(Car car, out string fault)
{
  fault = string.Empty;
  return false;
}

private Tuple<bool, string> IsCarFaulty(Car car)
{
  return Tuple.Create(false, string.Empty);
}

private ResultAndMessage IsCarFaulty(Car car)
{
  return new ResultAndMessage(false, string.Empty);
}

private bool IsCarFaulty(Car car)
{
  return false;
}

private string GetCarFault(Car car)
{
  return string.Empty;
}

基本上我的问题是,有没有一种情况比另一种更可取?如果我以int.TryParse为例。它使用 out 参数,但无法将其拆分为CanParseParse两种方法,即使不是更好,也同样有效。

4

6 回答 6

4

单独的CanParseParse方法的问题是你必须支付两次解析的成本——一次是在CanParse,然后是在Parse. 当解析非常复杂且耗时(例如,对于像这样的类型DateTime)时,这可能会特别成问题。

于 2012-08-17T23:48:32.303 回答
3

当返回多个值时,我更喜欢创建一个强类型的“结果”对象来封装方法的返回值。但是,需要返回多个值也可能表明您的方法做得太多并且可以重构。

例如,您的方法正在返回一个布尔值,以表明汽车是否有故障,以及一条消息。为什么不让方法返回失败类型的枚举值,然后让方法负责将该值转换为错误消息?

于 2012-08-17T23:49:06.307 回答
3

基本上我的问题是,有没有一种情况比另一种更可取?

当然可以,但我不认为有适用于所有情况的一般规则。只需根据具体情况选择您觉得更舒服的那个。

我通常避免使用out参数,因为它们不能很好地与 Linq 配合使用。

如果我以 int.TryParse 为例。它使用 out 参数,但无法将其拆分为 CanParse 和 Parse 两种方法,即使不是更好,也同样有效。

当然,它可以工作,但这意味着字符串将被解析两次,这是次优的。

当引入 int.TryParse 时,C# 没有可为空的类型 (编辑:实际上它有);现在你可以写一个这样的方法:

public static int? TryParseInt32(string s)
{
    int i;
    if (int.TryParse(s, out i))
        return i;
    return null;
}
于 2012-08-17T23:50:40.923 回答
2

选项:

  1. out
    • fast,这就是它在框架库中使用的原因,你不能用速度来换取其他任何东西
    • 糟糕的设计,不适合 LINQ 和任何链式代码
    • 易于编码
  2. Tuple<>
    • ,创建小对象,但在实践中很少会非常昂贵,因为据说它在 .NET 中得到了很好的优化。不过,我确实发现这是一个问题。
    • 可维护性差,没有字段名称,代码没有自我记录
    • 易于编码
  3. Result
    • 慢的
    • 良好的可维护性
    • 更多代码

显然,没有人能说什么对你的特定情况更好,所以选择你自己。

于 2012-08-18T00:30:35.643 回答
1

返回多个值的最佳方法是返回一个对象(一个将所有值包装在属性中的类),即

private ResultAndMessage IsCarFaulty(Car car)
{
  return new ResultAndMessage(false, string.Empty);
}

类 ResultAndMessage 有两个属性(布尔和字符串)

于 2012-08-17T23:52:17.130 回答
0

出于几个原因,我更喜欢使用for等方法bool返回。outTryXXXTryParseTryDeque

  1. 结果的“部分”是非常独立的东西,我喜欢它们保持分开。
  2. 返回类型在 this 的所有变体中都是相同的。所以这是一致的。
  3. out类型始终与调用的类型或对象密切相关,要么是类型本身(如 in ) ,要么int.TryParse是类型的类型参数(如Dictionary<TKey, TValue>.TryGetand ConcurrentQueue<T>.TryDequeue)。所以这是一致的。
  4. 它已成为 .NET 中易于识别的模式。所以这是一致的。

最后一点有一个缺点,即人们可能会在其他更合适的情况下转向它(假设输入有效且操作成功,如果不是这种情况则抛出异常,通常会更好)。

我避免out在其他情况下,它不能很好地链接,这反过来意味着它在 lambda 表达式中也不是很方便。

当它本身可能进一步使用时,我更喜欢封装不同值的对象。否则,它只是另一个需要学习的课程。

当某个东西同时返回两个不同的值有一个很好的明确原因时,我更喜欢元组,但它不符合上述关于新使用对象本身的内容。

最重要的是,我更喜欢首先只返回一个结果。

对于汽车故障示例,我要么返回一个表示故障的对象,如果它没有故障,则该对象可能为空,一个表示汽车状态的对象,其中“未找到故障”可能是一个可能的值,或者最重要的是,因为汽车可能有不止一个故障(并且确实似乎在 NCT/MOT/您所在国家/地区的等效故障之前开发了几个昂贵的故障)一个可枚举或可查询的对象,它可以让我迭代或查询以找到所有故障,Count == 0如果没有故障,它将是空的(如)。

于 2012-08-18T00:14:45.013 回答