在C#的文件操作场景中,遍历目录下的所有文件是高频需求,Directory.EnumerateFiles作为.NET提供的文件枚举方法,相比传统的Directory.GetFiles有更优的性能表现,尤其是在处理包含大量文件的目录时优势明显。它采用延迟执行(Lazy Evaluation)机制,不会一次性将所有文件路径加载到内存中,而是每次迭代时返回一个路径,大幅降低了内存占用。

Directory.EnumerateFiles基本用法
Directory.EnumerateFiles是System.IO命名空间下的静态方法,最常用的重载形式需要传入目标目录路径,还可以指定搜索模式和搜索选项。下面是一个基础的使用示例:
using System;
using System.IO;
class Program
{
static void Main()
{
string targetDir = @"C:test";
// 遍历目标目录下的所有txt文件,包含子目录
foreach (var filePath in Directory.EnumerateFiles(targetDir, "*.txt", SearchOption.AllDirectories))
{
Console.WriteLine(filePath);
}
}
}
上述代码中,EnumerateFiles返回的是一个可迭代的字符串集合,每个元素都是匹配到的文件的完整路径。SearchOption.AllDirectories表示搜索包含所有子目录,若只需要搜索当前目录,可以改为SearchOption.TopDirectoryOnly。
异步封装实现无阻塞遍历
Directory.EnumerateFiles本身是同步方法,如果在UI线程或者需要高并发的场景下使用,直接调用会导致线程阻塞。我们可以通过异步流(Async Streams)结合Task.Run将其封装为异步方法,避免阻塞主线程。下面是封装示例:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
class FileTraversalHelper
{
// 异步枚举文件的方法
public static async IAsyncEnumerable<string> EnumerateFilesAsync(string directoryPath, string searchPattern, SearchOption searchOption)
{
// 在后台线程执行同步的枚举操作
var filePaths = await Task.Run(() =>
{
return Directory.EnumerateFiles(directoryPath, searchPattern, searchOption);
});
// 逐个返回文件路径,保持延迟加载特性
foreach (var path in filePaths)
{
yield return path;
// 模拟异步等待,避免短时间大量迭代占用线程
await Task.Yield();
}
}
}
class Program
{
static async Task Main()
{
string targetDir = @"C:test";
await foreach (var filePath in FileTraversalHelper.EnumerateFilesAsync(targetDir, "*.txt", SearchOption.AllDirectories))
{
Console.WriteLine($"找到文件:{filePath}");
// 这里可以添加异步处理文件的逻辑,比如读取文件内容
}
}
}
上述代码使用了IAsyncEnumerable<string>作为返回类型,这是C# 8.0引入的异步流特性,允许我们以异步的方式逐个返回元素。Task.Yield的作用是让出当前线程的执行权,避免长时间占用线程池线程,适合在大量文件遍历的场景下使用。
Directory.EnumerateFiles与Directory.GetFiles的对比
两者的核心差异在于返回机制和内存占用,具体对比如下:
| 对比项 | Directory.EnumerateFiles | Directory.GetFiles |
|---|---|---|
| 返回机制 | 延迟加载,迭代时逐个返回 | 立即执行,一次性返回所有结果 |
| 内存占用 | 低,仅保存当前迭代的路径 | 高,需要保存所有匹配的路径 |
| 适用场景 | 大目录、需要逐步处理文件的场景 | 小目录、需要一次性获取所有路径的场景 |
| 执行时机 | 迭代到第一个元素时才开始搜索 | 调用方法时立即开始搜索 |
使用注意事项
- 路径合法性检查:调用EnumerateFiles前需要确保传入的目录路径存在,否则会抛出DirectoryNotFoundException异常,建议提前使用Directory.Exists方法判断。
- 异常处理:遍历过程中如果遇到没有访问权限的子目录,会抛出UnauthorizedAccessException,需要添加try-catch块处理异常,避免程序崩溃。
- 搜索模式规则:搜索模式支持通配符*和?,*匹配任意长度的字符,?匹配单个字符,比如*.log匹配所有后缀为log的文件。
- 性能取舍:如果后续需要多次使用所有文件路径,一次性获取后缓存可能比反复枚举更高效,需要根据实际场景选择。
总结
Directory.EnumerateFiles是C#中高效遍历文件的核心方法,其延迟加载的特性让它在处理大目录时比Directory.GetFiles更有优势。结合异步流封装后,还能实现无阻塞的文件遍历,适配更多开发场景。实际使用中需要根据目录大小、后续处理逻辑选择合适的文件遍历方式,同时注意异常处理和路径合法性校验,保证程序的稳定性。
C#Directory_EnumerateFiles异步枚举文件遍历修改时间:2026-07-13 11:27:14