防止相互引用的对象之间的无限循环?

时间:2013-07-15 09:18:45

标签: c# asp.net infinite-loop

好的,所以我不完全确定哪个标题适合我的问题,但是这里有描述:

我有对象而不是引用其他对象,以创建下拉列表,其中内容/值取决于在“父”下拉列表中选择的值。

我的下拉对象包含一个id和一个parentId(和其他东西,这里不相关)。

我想阻止用户制作无限循环,如下所示:

  • 清单1(取决于清单3)

  • 清单2(取决于清单1)

  • 清单3(取决于清单2)

我试过写一个递归方法来防止它,但我无法弄清楚逻辑。

有人能告诉我你如何确保一个物体不会“自行”地引用它吗?或者提供一个例子。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:3)

我能想到的最简单的方法是创建一个扁平的列表。递归迭代对象并将每个引用存储在列表中。当您找到新对象时,请检查列表中的每个对象。

您将遇到引用自身的对象或用完要搜索的对象。

此方法适用取决于您的要求,速度/内存/列表中的项目数。

由于所有对象都包含一个id,所以如果你需要检查值相等而不是引用相等,那么列表可以存储/检查

答案 1 :(得分:0)

如果你编写了一个递归函数来管理这些列表,一个解决方案可能是创建一个元素列表并将其作为参数传递给递归函数,并在每次迭代时将当前项添加到列表中。要停止递归功能,只需检查当前项目是否已添加到列表中。

答案 2 :(得分:0)

如果依靠每个列表的特定计数器遍历每个列表的实际元素,则不应该发现任何问题。引发无限循环的最可能方式是从外部源更改计数器的值。例如:

    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;因此解决方案:除了通过for循环之外,永远不要改变i

答案 3 :(得分:0)

感谢大家对此的意见。我跟詹姆斯建议使用了一个列表并最终得到了以下代码(除了我之外,其他任何人都可能有意义或没有意义)

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;
    }