从方法返回多个值

时间:2012-08-17 23:44:50

标签: c#

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

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参数,但无法将其分为两种方法 CanParse Parse ,如果不是更好的话。

6 个答案:

答案 0 :(得分:4)

单独的CanParseParse方法存在的问题是,您需要支付两次解析费用 - 一次在CanParse,然后又在Parse。当解析非常复杂且耗时时(例如对于像DateTime这样的类型),这可能尤其成问题。

答案 1 :(得分:3)

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

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

答案 2 :(得分: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;
}

答案 3 :(得分:2)

选项:

  1. out
    • ,这就是它在框架库中使用的原因,你无法用其他任何东西换取速度 在那些
    • 糟糕的设计,与LINQ和任何链式代码的关系不太好
    • 易于编码
  2. Tuple<>
    • ,创建小对象,但在实践中应该很少成本,因为据说它在.NET中得到了很好的优化。我确实曾多次发现这是一个问题。
    • 糟糕的可维护性,没有字段名称,代码没有自我记录
    • 易于编码
  3. Result
    • 良好的可维护性
    • 更多代码
  4. 显然没有人能说出你的具体情况会更好,所以选择自己。

答案 4 :(得分:1)

返回多个值的最佳方法是返回一个对象(一个包含属性中所有值的类)

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

与 类ResultAndMessage有两个属性(bool和string)

答案 5 :(得分:0)

我更喜欢bool返回out TryXXX方法,例如TryParseTryDeque等等,原因有几个。

  1. 结果的“部分”是非常独立的东西,我喜欢它们是分开的。
  2. 返回类型与此类型的所有变体相同。所以这是一致的。
  3. out类型始终与所调用的类型或对象紧密相关,可以是类型本身(如int.TryParse中),也可以是类型的类型参数(如{ {1}}和Dictionary<TKey, TValue>.TryGet)。所以这是一致的。
  4. 它已成为.NET中易于识别的模式。所以这是一致的。
  5. 最后一点有一个缺点,人们可能会在其他更合适的时候转向它(假设有效的输入和成功的操作,并且如果不是这样的情况下抛出异常,通常会更好)。

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

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

    我更喜欢元组,因为有一个明确的原因可以解释为什么某些东西同时返回两个不同的值,但它本身并不适合上面关于一个新的使用对象。

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

    对于汽车故障示例,我要么返回一个表示故障的对象,如果没有故障可能为空,一个对象表示汽车的状态“没有发现故障”可能是一个可能的值,或者最重要的是,因为汽车可能有多个故障(实际上似乎是在NCT / MOT /你的国家等同之前开发几个昂贵的故障)一个可以让我迭代或查询的可枚举或可查询的对象找出所有的错误,如果没有错误,那将是空的(如在out中)。