StackOverflowException引起的递归
我目前正在编写一个程序来帮助写Lore。每个书对象都可以是父母并且有孩子。这意味着每个孩子都可以有孩子等无限。我正在处理一个ToString()方法,它可以使用递归来解释这个问题,但我一直在收到一个StackOverflowException。StackOverflowException引起的递归
我知道这意味着什么,但我对我如何解决它有疑问。我对C#相当陌生,但拥有相当多的Java经验,所以如果你知道一个技巧或者我错过了什么,请让我知道!
所以我的问题是:如何避免StackOverflow异常?问题是在GetAllChildren()
编辑:
运行测试后,我应该得到的东西是这样的:
Name: a
Children:
b
c
d
e
与@lc代码。我得到以下输出:
Name: a
Children: No Children b
c
e
b
c
e
b
c
e
这里是类:
class Book
{
private String name;
private Book[] children;
private StringBuilder text;
private Boolean isParent;
public Book(String name, Book[] children, StringBuilder text, Boolean isParent)
{
this.name = name;
this.children = children;
this.text = text;
this.isParent = isParent;
}
/**
* Most likely all possible Constructors
* */
public Book(String name, Book[] children) : this(name, children, new StringBuilder("No Text"), true) { }
public Book(String name, String text) : this(name, new Book[0], new StringBuilder(text), false) { }
public Book(String name, StringBuilder text) : this(name, new Book[0], text, false) { }
public Book(String name) : this(name, new Book[0], new StringBuilder("No Text"), false) { }
public Book(Book[] children, String text) : this("Unnamed Book", children, new StringBuilder(text), true) { }
public Book(Book[] children, StringBuilder text) : this("Unnamed Book", children, text, true) { }
public Book(Book[] children) : this("Unnamed Book", children, new StringBuilder("No Text"), true) { }
public Book(StringBuilder text) : this("Unnamed Book", new Book[0], text, false) { }
public Book() : this("Unnamed Book", new Book[0], new StringBuilder("No Text"), false) { }
public String Name
{
get { return name; }
set { name = value; }
}
public Book[] Children
{
get { return children; }
set { children = value; }
}
/**
* Will Return the StringBuilder Object of this Text
* */
public StringBuilder Text
{
get { return text; }
set { text = value; }
}
public Boolean IsParent
{
get { return isParent; }
set { isParent = value; }
}
private void GetAllChildren(Book book, StringBuilder sb)
{
if (book.isParent)
{
GetAllChildren(book, sb);
}
else
{
sb.Append("\t");
foreach (Book b in children)
{
sb.Append(b.Name + "\n");
}
}
}
public override String ToString()
{
StringBuilder sChildren = new StringBuilder("No Children");
if (children.Length != 0)
{
GetAllChildren(this, sChildren);
}
return "Name: " + name + "\n" +
"Children: " + sChildren.ToString();
}
}
我想你的意思是:
if (book.isParent)
{
foreach (var child in book.Children)
GetAllChildren(child, sb);
}
否则你只是调用GetAllChildren
方法具有相同的参数(book, sb
)一遍又一遍。
附注 - 你仍然有一些问题,因为在GetAllChildren
停止条件是通过迭代的孩子,当它不应该(如果不是家长,它不应该有孩子)。它应该返回它自己的名字。此外,每个孩子还应该在上面的foreach循环中追加它的名字(或者实际上,每本书都应该附加自己的名字)。 (注意这些变化)的方法应该是静态的,因为它与任何给定的实例都不相关(这引出了下面的建议)。
建议 - 我建议像下面代替(未经测试,需要在格式化一些工作):
//name changed to reflect what it really does
//also changed to be an instance method (we no longer pass in a Book)
//added listThisBooksName parameter to allow supressing the topmost book's output
private void AppendAllChildren(StringBuilder sb, int level = 0,
bool listThisBooksName = false)
{
if (listThisBooksName)
{
//append ourself here
//first indent however far we need to
sb.Append(new String('\t', level));
//now add our name
sb.Append(this.Name);
//and a newline (you can strip the last one later if you want)
sb.Append('\n');
}
//forget the "isParent" property, just check if it has any children
//we don't need Children.Any() because the foreach will just iterate 0 times
//you might also consider using a List<Book> instead of an array for Children
if (this.Children != null)
foreach (var child in this.Children)
child.AppendAllChildren(sb, level+1, true);
}
这不是问题:
if (book.isParent)
{
GetAllChildren(book, sb);
}
你再次调用相同的方法?我认为上面应该遍历孩子,并为每个孩子Book
致电GetAllChildren
。只有输出名称如果您的Book
不有任何孩子。
您的递归在同一本书上递归,而该书的IsParent为true。如果这本书是父母,你可能想要通过所有的孩子递归。
通过在'stackoverflow.com查询 – 2013-03-14 09:15:37
@SiGanteng我正在考虑做笑话,但我不选择; P – OmniOwl 2013-03-14 09:16:29
在'isParent'分支内调用'GetAllChildren(book,sb)'后面的想法是什么? ?请注意,'book'和'sb'都没有被改变。 – 2013-03-14 09:19:03