【问题标题】:Prevent infinite loop between objects referencing each other?防止相互引用的对象之间的无限循环?
【发布时间】:2013-07-15 09:18:44
【问题描述】:
好的,所以我不完全确定哪个标题适合我的问题,但描述如下:
我有一些对象不能引用其他对象,以创建下拉列表,其中内容/值取决于在“父”下拉列表中选择的值。
我的下拉对象包含一个 id 和一个 parentId(和其他东西,这里不相关)。
我想防止用户进行无限循环,像这样:
列表 1(取决于列表 3)
列表 2(取决于列表 1)
列表 3(取决于列表 2)
我尝试编写递归方法来防止它,但我无法弄清楚逻辑。
谁能告诉我你将如何确保一个对象不会“下线”引用它自己?或者提供一个例子。
非常感谢任何帮助。
【问题讨论】:
标签:
c#
asp.net
infinite-loop
【解决方案1】:
我能想到的最简单的方法是创建一个扁平列表。递归迭代对象并将每个引用存储在列表中。当您发现新对象时,请检查列表中的每个对象。
您可能会遇到引用自身的对象,或者找不到要搜索的对象。
此方法是否合适取决于您的要求、速度/内存/列表中的项目数。
由于所有对象都包含一个 id,如果您需要检查值相等而不是引用相等,则列表可以存储/检查它
【解决方案2】:
如果您编写了一个递归函数来管理这些列表,一种解决方案可能是创建一个元素列表并将其作为参数传递给递归函数,然后每次迭代将当前项目添加到列表中。要停止递归函数,只需检查当前项目是否先前已添加到列表中。
【解决方案3】:
如果您通过依赖每个列表的特定计数器来遍历每个列表的实际元素,您应该不会发现任何问题。引发无限循环的最可能方法是从外部源更改计数器的值。示例:
for(int i = 0; i < max_i; i++)
{
if(val1[i] != null)
{
for(int j = 0; j < max_j; j++)
{
if(val2[j] != null)
{
//Delete or anything
//YOU CANNOT AFFECT NEITHER i NOR j DIRECTLY.
}
}
}
如果您想在内部部分考虑 j 的不同值,您应该依赖不同的变量。示例:
if(val2[j] != null)
{
int j2 = j;
//Do whatever with j2, never with j
}
通过这样做(将不同的计数器与不同的循环相关联),不会发生无限循环。当i = 1, 2, 3, 4 突然i 被“外部源”更改为2;因此解决方案:永远不要更改i,除非通过 for 循环。
【解决方案4】:
感谢大家对此的意见。我使用列表接受了 James 的建议,并最终得到了以下代码(这对除我以外的其他人可能有意义也可能没有意义)
public static bool BadParent(int fieldId, int childId, List<int> list)
{
if (list == null)
list = new List<int>();
bool returnValue = true;
var field = EkstraFelterBLL.getEkstraFeltUdfraEkstraFeltId(fieldId);
if (field != null)
{
if (field.ParentEkstraFeltId == childId)
returnValue = false; //loop reference, fail
else if (list.Contains(field.EkstraFeltId))
returnValue = false; //already been in the cycle, fail
else
{
list.Add(field.EkstraFeltId);
returnValue = BadParent(field.ParentEkstraFeltId, childId, list);
}
}
return returnValue;
}