Directory.GetFilesが配列を返すので、列挙子にしてみる。特にSearchOption.AllDirectoriesが指定されると、処理が返って来るまでにかなり時間がかかることがある。
フォルダーは再帰探索する必要があるので、実装は少し捻る必要がある。
public static class LinqExtensions
{
public static IEnumerable<string> FilesAsEnumerable(string path, string patterns)
{
foreach (var directoryPath in
Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly))
{
foreach (var filePath in
FilesAsEnumerable(directoryPath, patterns))
{
yield return filePath;
}
}
foreach (var filePath in
Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly))
{
yield return filePath;
}
}
}
これでもいいのだが、foreachだらけで見通しが悪い。全てクエリに置き換える。
public static class LinqExtensions
{
public static IEnumerable<string> FilesAsEnumerable(string path, string patterns)
{
var byDirectory =
from directoryPath in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly)
from filePath in FilesAsEnumerable(directoryPath, patterns)
select filePath;
var byFile =
from filePath in Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly)
select filePath;
return byDirectory.Concat(byFile);
}
}
これでファイルの列挙は以下のように記述できる。
foreach (var path in LinqExtensions.FilesAsEnumerable(@"C:project", "*.cs"))
{
Console.WriteLine(path);
}
ファイルの逐次探索が可能になったので、大量のファイルをパイプライン処理できるようになった。
なお、このコードは.NET 4.0以降では、Directory.EnumerateFilesとほぼ同じ動作となる。