C# Произвольно вложенный объект IEnumerable - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь написать несколько методов для работы с многослойным объектом IEnumerable в C#. В следующем примере показан метод с именем «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>>> легко и без перегрузки по одному?

Любые предложения приветствуются.

1 Ответ

3 голосов
/ 05 августа 2020

Вы могли бы просто c 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

Полная демонстрация здесь

Еще один способ generi c - создать метод расширения , например 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>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...