C# 如何将这个递归调用重写为循环?

C# 如何将这个递归调用重写为循环?,c#,recursion,windows-runtime,C#,Recursion,Windows Runtime,为了简化代码以便更好地理解,我尝试将此递归调用转换为while循环: function getMusic(IStorageFolder folder) { int cnt = 0; var folders = await folder.GetFoldersAsync(); if (folders != null) foreach (var fol in folders) await getMusic(fol); var f

为了简化代码以便更好地理解,我尝试将此递归调用转换为while循环:

function getMusic(IStorageFolder folder) {
    int cnt = 0;
    var folders = await folder.GetFoldersAsync();
    if (folders != null)
        foreach (var fol in folders)
            await getMusic(fol);

    var files = await folder.GetFilesAsync();
    foreach (var file in files)
    {
        MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
        source.Add(new Music("artist", "title", "album");
        cnt++;
    }
}
在代码中,
source
是类型为
Music
的可观察集合(包含三个参数,如
source.Add…
行所示)

然而,我一直不成功。下面是我的尝试,它似乎没有填充
源代码
列表

private async Task getMusic(IStorageFolder folder)
{
    Stack<StorageFolder> fold = new Stack<StorageFolder>();
    int count = 0; int firstTen = 0;
    var folders = await folder.GetFoldersAsync();

    foreach (var indvFolder in folders)
        fold.Push(indvFolder);

    while (count < fold.Count)
    {
        var fol = fold.Pop();
        if (firstTen > 9)
            break;
        var files = await fol.GetFilesAsync();
        foreach (var file in files)
        {
            MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
            source.Add(new Music("artist", "title", "album"));
            count++;
        }
        firstTen++;
    }
}
专用异步任务getMusic(IStorageFolder文件夹)
{
堆栈折叠=新堆栈();
int count=0;int firstTen=0;
var folders=await folder.GetFoldersAsync();
foreach(文件夹中的var indvFolder)
折叠。推(内折叠);
而(计数<折叠计数)
{
var fol=fold.Pop();
如果(前十名>9)
打破
var files=wait fol.getfileasync();
foreach(文件中的var文件)
{
MusicProperties MusicProperties=await file.Properties.GetMusicProperties异步();
添加(新音乐(“艺术家”、“标题”、“专辑”));
计数++;
}
firstTen++;
}
}

您试图在一个函数中完成太多的工作,这使代码变得复杂。从概念上讲,您在这里做了几件不同的事情,获取树中的所有文件夹,从所有文件夹中获取所有文件,以及从所有文件中获取所有属性。解散那些行动

遍历文件系统以获取所有文件是一项您已经非常熟悉的操作。事实上,由于这样的树将一直以相同的方式进行遍历,因此您甚至可以将异步树遍历推广到与结构无关的算法中:

public static async Task<IEnumerable<T>> TraverseAsync<T>(
    this IEnumerable<T> source
    , Func<T, Task<IEnumerable<T>>> childrenSelector)
{
    var queue = new Queue<T>(source);
    List<T> results = new List<T>();
    while (queue.Any())
    {
        var next = queue.Dequeue();
        results.Add(next);
        foreach (var child in await childrenSelector(next))
            queue.Enqueue(child);
    }
    return results;
}
它简化了代码:

private async Task<IEnumerable<Music>> getMusic(IStorageFolder rootFolder)
{
    var properties = await new[] { rootFolder }
        .TraverseAsync(folder => folder.GetFoldersAsync())
        .SelectManyAsync(folder => folder.GetFilesAsync())
        .SelectManyAsync(file => file.GetMusicPropertiesAsync());
    return properties.Select(prop => new Music());
}
专用异步任务getMusic(IStorageFolder根文件夹)
{
var properties=wait new[]{rootFolder}
.TraverseAsync(文件夹=>folder.GetFoldersAsync())
.SelectManyAsync(文件夹=>folder.GetFileAsync())
.SelectManyAsync(file=>file.GetMusicPropertiesAsync());
返回属性。选择(prop=>newmusic());
}
这里值得注意的是,我们还确保此方法实际返回任务本身中的结果,而不是通过改变列表作为副作用。这确保了
任务
类将负责所有必要的跨线程同步问题,并确保在异步操作实际完成之前(这可能是您的问题所在)无法访问结果集合。

fold.Pop()
更改
折叠.计数
fold.Count
不包括已处理的项目,因此
Count
没有意义

相反,使用
while(fold.Count>0)

此外,这些内容应该在循环中,因为原始代码访问了子文件夹的子文件夹:

foreach (var indvFolder in fol.GetFoldersAsync())
    fold.Push(indvFolder);
设置刚刚好

fold.Push(folder);

您是否成功地调试了代码。。你不能理解foreach循环吗?我在代码的每一行后面都有一个Debug.WriteLine来检查变量的值。为了保持代码的整洁,我已经从代码中删除了它们。那么,您的问题是什么?您知道如何使用调试器的快速监视吗
foreach (var indvFolder in fol.GetFoldersAsync())
    fold.Push(indvFolder);
fold.Push(folder);