有什么理由将 out 参数与 C# 7 元组 return 值一起使用?

Any reason tu use out parameters with the C# 7 tuple return values?

我刚刚观看了介绍 new features of C# 7 的视频。其中,它引入了 return 元组类型的可能性(例如:(int, int),我相信这只是 Tuple<int, int> 的语法糖)。因此,如果我们有一个方法 returning 多个值,在 C# 中有 3 种可能性:

(int first, int second) ReturnTuple()
{
    return (1, 2);
}

int ReturnOutParam(out int second)
{
    second = 2;
    return 1;
}

CustomObject ReturnObject()
{
    return new CustomObject
    {
        First = 1,
        Second = 2
    };
}

我相信,没有更多的方法可以做到 - 如果是,请指正。

这三种方法中哪一种是正确的?在什么情况下我们可以使用剩下的两个?对于每一个新的 C# 版本,我都有一种或两种设计模式在 .NET 世界中刚刚过时的感觉。一些功能非常有用(例如泛型、部分、LINQ、lambda、async/await 或 null 传播器)。其他的是非常有情境的(动态的,nameof)。还有一些对我来说没有意义(属性 自动初始化器、元组 return 值或局部函数)。

对我来说还是要看情况。例如对于 TryParse 它仍然更具可读性:

if (int.TryParse("123", out var i))
{
   // i
}

var (success, i) = int.TryParse("123");
if (success)
{
   // i
}

并且在大多数情况下 return 从方法中获取多个值是一种代码味道。您应该始终将 return 包装到 class 中,这比 FirstSecond.

更能描述您的价值观

首先,像 (int, int) 这样的元组是 ValueTuple<int, int> 的语法糖。 TupleValueTuple的区别是:

  • ValueTuple是值类型,所以不需要在堆上分配对象
  • ValueTuple 是可变的
  • ValueTuple 具有(显然)内置语言支持,它允许您通过自定义属性 (TupleElementNamesAttribute) 命名元组项。使用 Tuple,您只会得到 Item1Item2

对于每个新的语言版本,一些功能都已过时。例如,delegate { } 语法已被 lambda 表达式取代。您可能会争辩说 out 参数属于此类,但这是主观的。然而,所有功能都需要保留在那里以实现向后兼容性。

例如,bool int.TryParse(string input, out int value) 应该变成 int? int.TryParse(string input) 并在语言中包含可为 null 的值类型,但旧函数已经存在于框架中,因此它必须保留。

我的经验法则是:对私有方法或实用函数使用值元组,但对任何 public API 更喜欢完整的结构,这样感觉更干净。我通常避免使用 out 参数,但偶尔会使用私有方法。

我不明白为什么其中一些新功能对您没有意义:

  • 属性 自动初始化 finally 在那里,它们应该首先与自动属性一起实现,但由于时间限制可能被跳过.这明显提高了代码的可读性,并且添加了字段始终存在的功能。
  • 元组 return 值是您问题的主题,这也是对旧元组的明显可读性胜利。能够命名您的元组项不言自明。
  • 局部函数将主要用于实现迭代器模式,但我偶尔希望拥有这样的功能并通过使用 lambda 解决它。