有没有办法找出一个方法是否被同一个对象递归调用?

时间:2019-01-26 11:24:17

标签: c# recursion stack

我有一个对象结构,它具有罕见的但可能的循环。 (循环是正常的。)使用递归方法遍历结构时,循环会导致堆栈溢出。与其在所涉及的方法中添加另一个参数,不如找出“ this”中的当前方法是否已经在堆栈中,将是一个不错的选择。有可能吗?

2 个答案:

答案 0 :(得分:1)

我可能会选择一个ThreadLocal<T>计数器,在打电话时增加计数器,在离开时减少计数器。这样,您可以分别计算在每个线程上输入的时间。这也比扫描堆栈快得多。也可以将其与布尔值一起使用,仅用于递归检查。

private ThreadLocal<int> _recursiveCounter = new ThreadLocal<int>(() => 0);

public void MyMethod(int count)
{
    _recursiveCounter.Value++;
    try
    {
        if(_recursiveCounter.Value > 2)
            Trace.WriteLine($"Recursive exceeds 2 with {_recursiveCounter.Value}");

        if(count== 0)
            return;

        MyMethod(count-1);
    }
    finally
    {
        _recursiveCounter.Value--;
    }
}

当然,您可以将其包装在一个类中,然后将其与IDisposable using(...)组合在一起。

答案 1 :(得分:0)

我有一个非常相似的问题,以下是我如何解决的问题。基本上,我通过了HashSet<object>并尝试将this添加到该对象中。如果已添加,则this尚未处理。

// Dummy class representing an element in the structure
public class A : Strcuture { }

// Dummy class representing an element in the structure
public class B : Strcuture { }

// Dummy class representing an element in the structure
public class C : Strcuture { }

// Base Dummy class for Base Structure elements
public abstract class Strcuture {

    public List<Strcuture> Elements { get; } = new List<Strcuture>();


    public void AddElement(Strcuture element) {
        Elements.Add(element);
    }

    public void RecursiveMethod(HashSet<object> recursiveChecker) {
        if(recursiveChecker == null){
            recursiveChecker = new HashSet<object>();
        }

        var addedThis = recursiveChecker.Add(this);
        if(addedThis == false) {
            // this object has already been handled
            // throw exception?? return early etc
            throw new System.Exception("Already handled object");

        }
        foreach (var elem in Elements) {
            elem.RecursiveMethod(recursiveChecker);
        }
    }

}
class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        var b = new B();
        var c = new C();
        a.AddElement(b);
        b.AddElement(c);
        c.AddElement(a);
        // now our object structure contains a loop
        // A→B→C→A→B...
        a.RecursiveMethod(new HashSet<object>());
    }
}