Search code examples
c#recursionref-parameters

How to convert recursive procedure with side effects on ref param to recursive function returning a list?


It seems every time I go to write a recursive function I end up making it return void and using a ref parameter.

I'd much rather be able to write a function that just returns a result list.

Apologies if the answer is very simple - for some reason it elludes me.

Here's the code I have now:

public static void GetResrouces(string startURL, ref List<XDocument> result)
{
    var doc = XDocument.Parse(GetXml(startURL)); // GetXml ommitted - returns xml string
    var xs = new XmlSerializer(typeof(resourceList));
    var rdr = doc.CreateReader();
    if (xs.CanDeserialize(rdr))
    {
        var rl = (resourceList)xs.Deserialize(doc.CreateReader());

        foreach (var item in rl.resourceURL)
        {
            GetResrouces(startURL + item.location, ref result);
        }
    }
    else
    {
        result.Add(doc);
    }
}

public partial class resourceList
{

    private resourceListResourceURL[] resourceURLField;

    private string locationField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("resourceURL")]
    public resourceListResourceURL[] resourceURL
    {
        get
        {
            return this.resourceURLField;
        }
        set
        {
            this.resourceURLField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")]
    public string location
    {
        get
        {
            return this.locationField;
        }
        set
        {
            this.locationField = value;
        }
    }
}

I'd like to know if it can be rewritten to the prototype:

public static List<XDocument> GetResources(string startURL)

Solution

  • I guess something like:

    public static List<XDocument> GetResources(string startURL)
    {
        var result = new List<XDocument>();
        var doc = XDocument.Parse(GetXml(startURL));
        var xs = new XmlSerializer(typeof(resourceList));
        var rdr = doc.CreateReader();
        if (xs.CanDeserialize(rdr))
        {
            var rl = (resourceList)xs.Deserialize(doc.CreateReader());
    
            foreach (var item in rl.resourceURL)
            {
                result.AddRange(GetResources(startURL + item.location));
            }
        }
        else
        {
            result.Add(doc);
        }
        return result;
    }