如何在C#中保留Directory.EnumerateFiles的延迟特性并修改结果?
恢复Directory.EnumerateFiles的延迟返回行为
你的代码丢失延迟特性的核心原因是调用了.ToList()——这个方法会立即遍历所有文件并将结果全部加载到内存,直接抵消了Directory.EnumerateFiles的延迟枚举设计。
以下是修改后的代码,能保留延迟执行特性:
public Task<IEnumerable<string>> EnumerateStorageFiles( string DirectoryPathOnStorage, string SearchPattern = "*.*") { try { var fullRootPath = GetStorageRelatedPath(DirectoryPathOnStorage); // 保留原始延迟枚举,不提前加载所有文件 var delayedFileEnumerator = Directory.EnumerateFiles(fullRootPath, SearchPattern, new EnumerationOptions() { IgnoreInaccessible = true, RecurseSubdirectories = true, AttributesToSkip = FileAttributes.System, ReturnSpecialDirectories = false }) // 延迟执行路径转换:仅当枚举元素被访问时才计算相对路径 .Select(filePath => Path.GetRelativePath(StorageBasePath, filePath)); return Task.FromResult(delayedFileEnumerator); } catch { return Task.FromResult(Enumerable.Empty<string>()); } }
关键修改说明
- 移除
.ToList()调用:避免提前触发全量文件枚举和内存加载 - 使用
.Select()做延迟转换:相对路径的计算会推迟到每个元素被访问时才执行,和Directory.EnumerateFiles的延迟逻辑保持一致 - 保留原有异常捕获:处理目录不存在等初始化阶段的异常,返回空枚举
额外优化(可选)
如果需要处理枚举过程中单个路径转换失败的情况(比如权限问题导致路径无法转换),可以封装一个迭代器方法来逐个处理异常,避免整个枚举终止:
private IEnumerable<string> ConvertPathsSafely(IEnumerable<string> fullFilePaths) { foreach (var fullPath in fullFilePaths) { try { yield return Path.GetRelativePath(StorageBasePath, fullPath); } catch { // 跳过转换失败的路径,或记录日志 continue; } } } // 在主方法中替换Select调用: var delayedFileEnumerator = ConvertPathsSafely(Directory.EnumerateFiles(...));
内容的提问来源于stack exchange,提问作者Shayan Firoozi
相关产品推荐
相关产品推荐

