如果目录内容在迭代过程中发生变化,Directory.EnumerateFiles 会发生什么?

Har*_*lse 6 c# file enumerate system.io.directory getfiles

我已经阅读了关于Directory.EnumerateFiles和之间差异的讨论Directory.GetFiles

我知道他们在内部都使用 System.IO.FileSystemEnumerableFactory.CreateFileNameIterator()

不同之处在于EnumerateFiles可能会使用延迟执行(lazy),而会使用GetFiles()a ToArray,因此该函数已经被执行了。

但是如果在迭代过程中将文件和文件夹添加到字典中会发生什么。迭代是否只迭代在EnumerateFiles()?期间存在的项目?

更糟糕的是:如果在迭代过程中删除文件会发生什么:它们还会被迭代吗?

Har*_*lse 6

感谢 Michal Komorowski。然而,当我自己尝试他的解决方案时,我发现 Directory.EnumerateFiles 和 Directory.GetFiles() 之间存在显着区别:

Directory.CreateDirectory(@"c:\MyTest");
// Create fies: b c e
File.CreateText(@"c:\MyTest\b.txt").Dispose();
File.CreateText(@"c:\MyTest\c.txt").Dispose();
File.CreateText(@"c:\MyTest\e.txt").Dispose();

string[] files = Directory.GetFiles(@"c:\MyTest");
var fileEnumerator = Directory.EnumerateFiles(@"c:\MyTest");

// delete file c; create file a d f
File.Delete(@"c:\MyTest\c.txt");
File.CreateText(@"c:\MyTest\a.txt").Dispose();
File.CreateText(@"c:\MyTest\d.txt").Dispose();
File.CreateText(@"c:\MyTest\f.txt").Dispose();

Console.WriteLine("Result from Directory.GetFiles");
foreach (var file in files) Console.WriteLine(file);
Console.WriteLine("Result from Directory.EnumerateFiles");
foreach (var file in fileEnumerator) Console.WriteLine(file);
Run Code Online (Sandbox Code Playgroud)

这将给出不同的输出。

Result from Directory.GetFiles
c:\MyTest\b.txt
c:\MyTest\c.txt
c:\MyTest\e.txt
Result from Directory.EnumerateFiles
c:\MyTest\b.txt
c:\MyTest\d.txt
c:\MyTest\e.txt
c:\MyTest\f.txt
Run Code Online (Sandbox Code Playgroud)

结果:

  • GetFiles 仍然看到旧文件:如预期的 BCE
  • EnumerateFiles 看到了新文件 D 和 F。它正确地跳过了删除的文件 C,但它错过了新文件 A。

所以 EnumerateFiles 和 GetFiles 之间的用法差异不仅仅是性能。

  • GetFiles 返回调用函数时文件夹中的文件。这是可以预料的,因为它只是对字符串集合的枚举
  • EnumerateFiles 正确跳过已删除的文件,但没有看到所有添加的文件。如果在枚举结果时文件夹发生变化,则结果相当不确定。

因此,如果您希望在枚举时您的文件夹发生变化,请仔细选择所需的功能

  • 期望 GetFiles 查看已删除的文件
  • 预计 EnumerateFiles 会错过一些新文件。