我认为从代码可读性的角度来看,最好的办法是编写一个递归函数。递归函数是一个调用自身的函数,直到它到达不需要调用任何其他函数的地步。
为了说明,n的阶乘,写成n!并定义为数量 1 x 2 x 3 x ... x n(其中 n 是正整数)可以很容易地以递归方式定义,如下所示。
public int factorial(int n)
{
if (n < 0)
{
throw new Exception("A factorial cannot be calculated for negative integers.");
}
if (n == 0 || n == 1)
{
// end condition, where we do not need to make a recursive call anymore
return 1;
}
else
{
// recursive call
return n * factorial(n - 1);
}
}
注意:0!和1!被定义为 1。
同样,枚举给定路径下的所有文件和文件夹的方法也可以递归定义。这是因为文件和文件夹具有递归结构。
因此,可以使用如下方法:
public static List<FileSystemInfo> GetAllFilesAndFolders(string folder)
{
// NOTE : We are performing some basic sanity checking
// on the method's formal parameters here
if (string.IsNullOrEmpty(folder))
{
throw new ArgumentException("An empty string is not a valid path.", "folder");
}
if (!Directory.Exists(folder))
{
throw new ArgumentException("The string must be an existing path.", "folder");
}
List<FileSystemInfo> fileSystemInfos = new List<FileSystemInfo>();
try
{
foreach (string filePath in Directory.GetFiles(folder, "*.*"))
{
// NOTE : We will add a FileSystemInfo object for each file found
fileSystemInfos.Add(new FileInfo(filePath));
}
}
catch
{
// NOTE : We are swallowing all exceptions here
// Ideally they should be surfaced, and at least logged somewhere
// Most of these will be security/permissions related, i.e.,
// the Directory.GetFiles method will throw an exception if it
// does not have security privileges to enumerate files in a folder.
}
try
{
foreach (string folderPath in Directory.GetDirectories(folder, "*"))
{
// NOTE : We will add a FileSystemInfo object for each directory found
fileSystemInfos.Add(new DirectoryInfo(folderPath));
// NOTE : We will also add all FileSystemInfo objects found under
// each directory we find
fileSystemInfos.AddRange(GetAllFilesAndFolders(folderPath));
}
}
catch
{
// NOTE : We are swallowing all exceptions here
// Ideally they should be surfaced, and at least logged somewhere
// Most of these will be security/permissions related, i.e.,
// the Directory.GetDirectories method will throw an exception if it
// does not have security privileges to enumerate files in a folder.
}
return fileSystemInfos;
}
需要注意的是,此方法将“遍历”文件夹下的整个目录结构,并且在“遍历”整个层次结构之前不会返回。因此,如果要找到的对象很多,可能需要很长时间才能返回。
另外需要注意的是,这个方法的可读性可以通过使用 Lambda 表达式和扩展方法进一步提高。
注意:使用 Directory.GetFiles 和 Directory.GetDirectories 递归子文件夹的问题在于,如果抛出任何异常(例如,与安全权限相关),该方法将不会返回任何内容,而手动递归则允许处理那些异常并且仍然得到一组文件。