MNeg
MNeg

Reputation: 25

Try-Catch with Yield return in a Recursive Method

I need to implement a try catch in a recursive method, but i can't figure out how to do it. This is the code:

    private IEnumerable <FileItem> FilesToDownload(FileItem file)
    {
        logger = LogManager.GetLogger(GetType());

        using (var wb = new WebDavSession(webDavUrl, new NetworkCredential(user, psw)))
        using (Task<IList<WebDavSessionItem>> task = wb.ListAsync(file.Path))
        {
            task.Wait();
            foreach (var item in task.Result)
            {
                FileItem retFile = item.ToFileItem();
                logger.Info("Going Into " + retFile.Path);
                if (item.IsFolder == true)  
                {
                    foreach (var inner in FilesToDownload(retFile))
                    {
                        yield return inner;
                    }
                }
                else
                {
                    yield return retFile;
                }
            }
        } 
    }

This method helps me to find out files into nested folders (in a cloud), so the recursive is necessary.

Whay do you suggest?

Upvotes: 1

Views: 116

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062945

What you can't do is have a try/catch block around a yield return statement - that violates CS1626.

But: you can still use try/catch - you just need to be creative in the layout. For example:

foreach (var item in task.Result)
{
    IEnumerable<FileItem> subItems = null;
    FileItem subItem = null;

    try
    {
        FileItem retFile = item.ToFileItem();
        logger.Info("Going Into " + retFile.Path);
        if (item.IsFolder == true)
        {
            subItems = FilesToDownload(retFile);
        }
        else
        {
            subItem = retFile;
        }
    }
    catch { /* your code here */ }
    if (subItem != null) yield return subItem;
    if (subItems != null)
    {
        foreach (var x in subItems) yield return x;
    }
}

Additional thoughts:

  • a Stack<T> or Queue<T> may be a more suitable approach than deep recursion
  • the task.Wait() is not good and could deadlock your code; unfortunately there is currently no good pattern for "async enumerables"

Upvotes: 1

Related Questions