C# 递归中的返回值

C# 递归中的返回值,c#,C#,我的问题“现代语言如何处理局部变量和递归?”来自编写文件搜索方法。基本上 public ArrayList getMusicFiles(string directory){ ArrayList songpaths = new ArrayList(); string[] localFiles = System.IO.Directory.GetFiles(directory); for(int i=0; i<localFiles.Length-1; i++)

我的问题“现代语言如何处理局部变量和递归?”来自编写文件搜索方法。基本上

public ArrayList getMusicFiles(string directory){
    ArrayList songpaths = new ArrayList();

    string[] localFiles = System.IO.Directory.GetFiles(directory);
    for(int i=0; i<localFiles.Length-1; i++)
        if(isMusicFile(localFiles[i]))
            songpaths.add(localFiles[i]);

    string[] localFolders = System.IO.Directory.GetDirectories(directory);
    for(int i=0; i<localFolder.length-1; i++)
        getMusicFiles(localFolder[i]);
}
public ArrayList getMusicFiles(字符串目录){
ArrayList SongPath=新的ArrayList();
字符串[]localFiles=System.IO.Directory.GetFiles(目录);
对于(int i=0;i
publicArrayList GetMusicFile(字符串目录,ArrayList歌曲路径){
字符串[]localFiles=System.Io.Directory.GetFiles(rootDir);

对于(int i=0;i代码有点难读,但无论如何……我建议编写一个实际用于递归的方法的私有版本,并将ArrayList作为参数传递。

注意,我是在假设您打算使用
目录
参数代替
rootDir
类级别v的情况下操作的可变的


你有两个选择

这是一种简单但更有效的方法 在本例中,您将通过list对象。我将使用
list
而不是
ArrayList

public List<string> getMusicFiles(string directory) {
  var list = new List<string>();
  getMusicFiles(list, directory);
  return list;
}

private void getMusicFilesInternal(List<string> songpaths, string directory)
{
  string[] localFiles= System.IO.Directory.GetFiles(directory);
  for(int i=0; i<localFiles.Length-1; i++) {
    if(isMusicFile(localFiles[i])) {
      songpaths.add(localFiles[i]);
    }
  }
  string[] localFolders= System.IO.Directory.GetDirectories(directory);
  for(int i=0; i<localFolder.Length-1; i++) {
    getMusicFiles(songpaths, localFolder[i]);
  }
}

如果您担心
foreach
的性能,请不要担心。首先,您应该先为可读性编码,然后为性能编码,只有在发现瓶颈时才进行优化。其次,当您在数组类型上使用
foreach
时,编译器会将其转换为等效的基于
长度的迭代,而不是而不是通过一个
IEnumerator

来访问数组,你可以通过传入当前列表来完成,这样你就可以将列表附加到递归中

public ArrayList getMusicFiles(string directory, ArrayList data, string rootDir) {
    string[] localFiles = System.IO.Directory.GetFiles(rootDir);
    for (int i = 0; i < localFiles.Length - 1; i++) 
        if (isMusicFile(localFiles[i])) 
            songpaths.add(localFiles[i]);

    string[] localFolders = System.IO.Directory.GetDirectories(rootDir);
    for (int i = 0; i < localFolder.length - 1; i++) 
        data.AddRange(getMusicFiles(localFolder[i]));
    return data;
}
公共ArrayList GetMusicFile(字符串目录、ArrayList数据、字符串根目录){ 字符串[]localFiles=System.IO.Directory.GetFiles(rootDir); for(int i=0;i
您可以选择使用累加器策略,并将工作交给需要将数组传递给它的助手函数:

public List<string> GetMusicFiles(string directory)
{
    List<string> songPaths = new List<string>();

    GetMusicFilesHelper(directory, songPaths);

    return songPaths;
}

private void GetMusicFilesHelper(string directory, List<string> paths)
{
    string[] localFiles = Directory.GetFiles(directory);
    for(int i = 0; i < localFiles.Length; i++) 
    {
        if(isMusicFile(localFiles[i])) paths.Add(localFiles[i]);
    }

    string[] localFolders = Directory.GetDirectories(directory);
    for(int i = 0; i < localFolder.length; i++)
    {
        GetMusicFilesHelper(localFolder[i], paths);
    }
}
如果您使用的是.Net 4.0+,则这将成为一个具有以下功能的步态:

public IEnumerable GetMusicFile(字符串目录)
{
返回目录.EnumerateFiles(目录“***”,SearchOption.AllDirectory)
其中(ff=>IsMusicFile(ff));
}

你是怎么在2分钟内想到这个的?+1,但是
Directory.GetFiles(路径“**”,SearchOption.AllDirectories)
消除了递归的需要。在这种情况下,也可以这样做,但不缓冲所有文件。@sixlettervariables如果只返回延迟执行
IEnumerable
…我明白你的意思,但是如果目录结构庞大,那么这种方法实际上会变得更糟,因为它会拖拽整个文件列表这段代码虽然有点复杂,但会一个接一个地将文件拉入每个级别。表示文件系统布局的唯一对象在任何时候都不符合收集条件,将是
字符串[]
仍在处理的每个目录的对象。@cdhowie:与让Win32在引擎盖下处理相比,您的案例对更大结构的容忍度会更低。最终,如果内存中的文件数量超过了可以处理的数量,这两个文件都会消失。递归版本会更快消失。为什么有人会使用
ArrayList
而不是
List
这里?您如何处理
目录
参数?
public IEnumerable<string> getMusicFiles(string directory)
{
  string[] localFiles= System.IO.Directory.GetFiles(directory);
  for(int i=0; i<localFiles.Length-1; i++) {
    if(isMusicFile(localFiles[i])) {
      yield return localFiles[i];
    }
  }
  string[] localFolders= System.IO.Directory.GetDirectories(directory);
  for(int i=0; i<localFolder.Length-1; i++) {
    foreach (var j in getMusicFiles(localFolder[i])) {
      yield return j;
    }
  }
}
public IEnumerable<string> getMusicFiles(string directory)
{
  foreach (var file in System.IO.Directory.GetFiles(directory)) {
    if (isMusicFile(file)) {
      yield return file;
    }
  }

  foreach (var dir in System.IO.Directory.GetDirectories(directory)) {
    foreach (var musicFile in getMusicFiles(dir)) {
      yield return musicFile;
    }
  }
}
public ArrayList getMusicFiles(string directory, ArrayList data, string rootDir) {
    string[] localFiles = System.IO.Directory.GetFiles(rootDir);
    for (int i = 0; i < localFiles.Length - 1; i++) 
        if (isMusicFile(localFiles[i])) 
            songpaths.add(localFiles[i]);

    string[] localFolders = System.IO.Directory.GetDirectories(rootDir);
    for (int i = 0; i < localFolder.length - 1; i++) 
        data.AddRange(getMusicFiles(localFolder[i]));
    return data;
}
public List<string> GetMusicFiles(string directory)
{
    List<string> songPaths = new List<string>();

    GetMusicFilesHelper(directory, songPaths);

    return songPaths;
}

private void GetMusicFilesHelper(string directory, List<string> paths)
{
    string[] localFiles = Directory.GetFiles(directory);
    for(int i = 0; i < localFiles.Length; i++) 
    {
        if(isMusicFile(localFiles[i])) paths.Add(localFiles[i]);
    }

    string[] localFolders = Directory.GetDirectories(directory);
    for(int i = 0; i < localFolder.length; i++)
    {
        GetMusicFilesHelper(localFolder[i], paths);
    }
}
public List<string> GetMusicFiles(string directory)
{
    List<string> songPaths = new List<string>();

    // TODO: pick a better search pattern
    string[] paths = Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories);
    foreach (string path in paths)
    {
        if (IsMusicFile(path))
        {
            songPaths.Add(path);
        }
    }
}
public IEnumerable<string> GetMusicFiles(string directory)
{
    return Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories)
                    .Where(ff => IsMusicFile(ff));
}