Нет простого способа сделать это.
Вы можете обойти это, определив тип C #, который может хранить либо одно значение, либо последовательность значений - используя нотацию F #, это будет:
type EnumerationResult<'a> =
| One of 'a
| Seq of seq<'a>
(переведите это на C # так, как вам нравится: -))
Теперь вы можете написать что-то вроде:
static IEnumerable<EnumerationResult<string>> Visitor
(string root, string filter) {
foreach (var file in Directory.GetFiles(root, filter))
yield return EnumerationResult.One(file);
foreach (var subdir in Directory.GetDirectories(root))
yield return EnumerationResult.Seq(Visitor(subdir, filter))
}
}
Чтобы использовать его, вам нужно написать функцию, которая выравнивает EnumerationResult, который может быть методом расширения в C # со следующей сигнатурой:
IEnumerable<T> Flatten(this IEnumerable<EnumerationResult<T>> res);
Теперь, это часть, где это становится сложным - если бы вы реализовали это простым способом, он все равно содержал бы «forach» для перебора вложенных результатов «Seq». Однако я считаю, что вы могли бы написать оптимизированную версию, которая не имела бы квадратичной сложности.
Хорошо ... Я думаю, что это тема для поста в блоге, а не что-то, что могло бы быть полностью описано здесь :-), но, надеюсь, это показывает идею, которой вы можете следовать!
[РЕДАКТИРОВАТЬ: Но, конечно, вы также можете использовать простую реализацию "Flatten", которая будет использовать "SelectMany" только для того, чтобы сделать синтаксис вашего кода итератора C # лучше]