以正确的方式从递归方法返回并填充一个集合

本文关键字:填充 集合 一个 返回 方式 递归方法 | 更新日期: 2023-09-27 18:06:41

我要写一个方法(或两个方法),它应该返回文件夹层次结构中所有文件的列表(包括所有子文件夹)。当我填充一个全局List时,我知道如何处理它。这对我来说很有效(这不是我的问题)。但是我想在方法中填充List,因此我遇到了递归的问题。到目前为止,我在这里:

public List<string> GetAllFiles(string path)
{
    List<string> files = new List<string>();
    FindFiles(files, path);
    return files;
}
private void FindFiles(List<string> files, string path)
{
    if (Directory.Exists(path))
    {
        try
        {
            foreach (string folder in Directory.GetDirectories(path))
            {
                FindFiles(files, folder);
            }
            foreach (string file in Directory.GetFiles(path).ToArray())
            {
                files.Add(file);
            }
        }
        catch (Exception)
        {
            // ignored
        }
    }
}

这个可以工作,但是我传递List作为参考,在我看来这不是一个干净的方式。如何"正常"处理?

以正确的方式从递归方法返回并填充一个集合

您的方法非常干净,因为它允许您一次创建列表,填写它,然后返回给调用者,而不需要创建重复的列表。

给定返回List<string>的方法签名,另一种替代方法会稍微浪费一些,因为它会在层次结构的每个级别创建一次性列表:

public List<string> GetAllFiles(string path) {
    var res = new List<string>();
    if (Directory.Exists(path)) {
        try {
            foreach (var folder in Directory.GetDirectories(path)) {
                res.AddRange(GetAllFiles(folder));
            }
            foreach (var file in Directory.GetFiles(path)) {
                res.Add(file);
            }
        } catch (Exception) {
            // ignored
        }
    }
    return res;
}

LINQ使其更加简洁,但方法保持不变:

public List<string> GetAllFiles(string path) {
    if (!Directory.Exists(path)) {
        return new List<string>();
    }
    try {
        return Directory.GetDirectories(path).SelectMany(folder => GetAllFiles(folder))
            .Concat(Directory.GetFiles(path)).ToList();
    } catch (Exception) {
        return new List<string>();
    }
}

您可以尝试使用yield return添加到您的列表中。

public List<string> GetAllFiles(string path)
{
    List<string> files = new List<string>();
    foreach (string file in FindFiles(path))
    {
        files.Add(file);
    }
    return files;
}
private IEnumerable<string> FindFiles(string path)
{
    if (Directory.Exists(path))
    {
        try
        {
            foreach (string folder in Directory.GetDirectories(path))
            {
                foreach (string file in FindFiles(files, folder))
                {
                    yield return file;
                }
            }
            foreach (string file in Directory.GetFiles(path).ToArray())
            {
                yield return file;
            }
        }
        catch (Exception)
        {
            // ignored
        }
    }
}