将ValueTuple转换为IEnumerable

是否有更好的方法来执行以下操作:

public static class ValueTupleAdditions { public static IEnumerable ToEnumerable(this ValueTuple tuple) { yield return tuple.Item1; yield return tuple.Item2; } public static IEnumerable ToEnumerable(this ValueTuple tuple) { yield return tuple.Item1; yield return tuple.Item2; yield return tuple.Item3; } [etc] } 

编辑:因为人们要求用例,所以你去。

 using Xunit; namespace Whatever { public class SomeTestClass { public static IEnumerable<(string, Expression<Func>, string)> RawTestData() { yield return ("Hello", str => str.Substring(3), "lo"); yield return ("World", str => str.Substring(0, 4), "worl"); } public static IEnumerable StringTestData() { return RawTestData().Select(vt => new object[] { vt.Item1, vt.Item2, vt.Item3 }); // would prefer to call RawTestData().Select(vt => vt.ToArray()) here, but it doesn't exist. } [Theory, MemberData(nameof(StringTestData))] public void RunStringTest(string input, Expression<Func> func, string expectedOutput) { var output = func.Compile()(input); Assert.Equal(expectedOutput, output); } } } 

一点反思:

 namespace ConsoleApp1 { using System; using System.Collections.Generic; using System.Linq; public class Program { public static void Main() { var tuple = (1, 2, 3, 4, 5, 6, 7); var items = ToEnumerable(tuple); foreach (var item in items) { Console.WriteLine(item); } } private static IEnumerable ToEnumerable(object tuple) { if (tuple.GetType().GetInterface("ITupleInternal") != null) { foreach (var prop in tuple.GetType() .GetFields() .Where(x => x.Name.StartsWith("Item"))) { yield return prop.GetValue(tuple); } } else { throw new ArgumentException("Not a tuple!"); } } } } 

一种方法是通过ITuple界面 。

 public interface ITuple { int Length { get; } object this[int index] { get; } } 

它仅适用于.NET Core 2.0,Mono 5.0和.NET Framework的下一版本(未发布,遵循4.7)。 它不是(也永远不会)通过ValueTuple包作为旧框架的附加组件。

此API旨在供C#编译器用于将来的模式工作。