如何将对 ref 参数有副作用的递归过程转换为返回列表的递归函数?
似乎每次我去编写递归函数时,我最终都会使其返回 void 并使用 ref 参数。
我更愿意编写一个只返回结果列表的函数。
如果答案很简单,我很抱歉 - 由于某种原因它让我困惑。
这是我现在的代码:
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;
}
}
}
我想知道是否可以将其重写为原型:
public static List<XDocument> GetResources(string startURL)
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我猜是这样的:
I guess something like:
代码看起来很好(减去参数上不必要的
ref
)。一种选择是将递归方法包装在非递归同伴中:The code looks fine as is (minus the unnecessary
ref
on the parameter.) One option is to wrap the recursive method in a non-recursive companion:一方面,作为 ref 参数一开始就没有任何意义。您很可能不理解
ref
参数 - 请参阅我的文章关于这个主题。由于这是自然递归的,我可能会这样写:
您可以以递归方式保持它并在每个级别创建一个新列表,但对我来说有点难看。上面为您提供了您想要的 public API,但没有向左、右和中心分配集合。
现在您可以以非递归方式编写它,基本上是通过创建一个要处理的 URL 队列来完成:
对于我来说,现在已经太晚了,无法确定这是否以相同的顺序给出结果- 我怀疑不是 - 但希望这并不重要。
(您真的没有一个名为
resourceList
的类型吗?ResourceList
,拜托!)For one thing, there's absolutely no point in that being a
ref
parameter in the first place. It's quite possible that you don't understandref
parameters - see my article on this topic.As this is naturally recursive, I'd probably write it like this:
You can keep it in a recursive fashion and create a new list at every level, but it feels a little ugly to me. The above gives you the public API you want, but without allocating collections left, right and centre.
Now you could write it in a non-recursive fashion, basically by creating a queue of URLs to work through:
It's too late in the day for me to work out whether this gives the results in the same order - I suspect it doesn't - but hopefully that's not important.
(You don't really have a type called
resourceList
do you?ResourceList
, please!)嗯,我有一个偶尔使用过的模式,我想将它作为一个选项来展示。然而,当我试图按照书面方式解决它时,我的大脑有点不舒服,所以我们达成了一项协议(我的大脑和我),我们只会找出一个简单的版本来向您展示。
它甚至可能不太适用于您的具体问题,但这是我过去使用的一种方式,当我希望以不可变的方式完成事情时,这似乎正是您所寻找的。
所以,这个模式是有其价值的。它不是 XML,它没有分支,但它是一个简洁的示例,说明非变异递归很容易实现,并且(对我来说)比尝试通过变异
来实现相同的事情更容易理解字符串生成器。
确实,您的特定示例似乎(对我来说)更好地作为两步解决方案,在开始时创建了一个列表返回值。 :)
Well, I have a pattern I have used on occasion, and I wanted to show it as an option. However, my brain was a bit ticked off when I tried to tackle it as written, so instead we came to an agreement (my brain and I) that we would just figure out a simple version to show you.
It may not even be quite applicable to your specific question, but it's one way I have used in the past when I wanted things done in a non-mutable fashion, which seemed to be what you were looking for.
So, there is the pattern, for what it's worth. It's not XML, it doesn't branch, but it's a succinct example of when a non-mutating recursion is easy to implement and is more understandable (to me) than trying to implement the same thing by, say, mutating a
StringBuilder
.Really, your particular example seems to flow better (to me) as the two-step solution with a single List return value created at the beginning. :)