C# 任意嵌套的 IEnumerable 对象

C# Arbitrarily Nested IEnumerable object

我正在尝试编写一些方法来处理 C# 中的多层 IEnumerable 对象。以下示例是名为“ConsoleWrite”的方法,用于将 IEnumerable 对象中的每个字符串打印到控制台。

public void ConsoleWrite(IEnumerable<string> StringData)
{
    foreach (var EachString in StringData)
    {
        Console.Write(EachString);
    }
}

“ConsoleWrite”方法的用法。

List<string> Test1 = new List<string>();
Test1.Add("123");
Test1.Add("456");
ConsoleWrite(Test1);

运行良好,输出为“123456”。但是,当涉及到 List<List<string>> 的情况时,这个 ConsoleWrite 方法需要如下重载。

public void ConsoleWrite(IEnumerable<IEnumerable<string>> StringData)
{
    foreach (var EachString in StringData)
    {
        ConsoleWrite(EachString);
    }
}

测试案例List<List<string>>.

List<List<string>> Test2 = new List<List<string>>();
Test2.Add(Test1);
Test2.Add(Test1);
ConsoleWrite(Test2)

另外,对于List<List<List<string>>>的情况,这个ConsoleWrite方法需要重载为public void ConsoleWrite(IEnumerable<IEnumerable<IEnumerable<string>>> StringData)。我想知道是否有任何方法可以轻松处理任意嵌套的列表 IEnumerable<...<IEnumerable<string>>> 而无需逐一重载?

欢迎提出任何建议。

你可以只使用非泛型 IEnumerable、一些 模式匹配 递归

public static void ConsoleWrite(IEnumerable source)
{
   foreach (var item in source)
      if (item is string str)
         Console.WriteLine(str);
      else if (item is IEnumerable enumerable)
         ConsoleWrite(enumerable);
}

例子

var list = new List<string> {"1", "2", "3"};

ConsoleWrite(list);

var list2 = new List<List<string>>
   {
      new List<string>(){"4", "5", "6"},
      new List<string>(){"7", "8", "9"}
   };

ConsoleWrite(list2);

输出

1
2
3
4
5
6
7
8
9

Full Demo here


另一种更通用的方法是创建一个扩展方法,就像SelectMany递归

public static class Extensions
{
   public static IEnumerable<T> FlattenMany<T>(this IEnumerable source)
   {
      foreach (var item in source)
         if (item is T t)
            yield return t;
         else if (item is IEnumerable enumerable)
            foreach (var elem in enumerable.FlattenMany<T>())
               yield return elem;
   }
}

用法

var list2 = new List<List<string>>
{
   new List<string>() {"4", "5", "6"},
   new List<string>() {"7", "8", "9"}
};

var results = list2.FlattenMany<string>();