C# 有没有办法确定一个方法是否被同一个对象递归调用?
我有一个对象结构,具有罕见但可能的循环。循环是正常的。使用递归方法遍历结构时,循环会导致堆栈溢出。与其在涉及的方法中添加另一个参数,不如找出“this”中的当前方法是否已经在堆栈中。这可能吗?我可能会选择像ThreadLocal计数器这样的东西,在呼叫时增加它,在离开时减少它。通过这种方式,您可以分别计算它在每个线程上输入的时间。这也比扫描堆栈快得多。这也可以用于布尔值,仅用于递归检查C# 有没有办法确定一个方法是否被同一个对象递归调用?,c#,recursion,stack,C#,Recursion,Stack,我有一个对象结构,具有罕见但可能的循环。循环是正常的。使用递归方法遍历结构时,循环会导致堆栈溢出。与其在涉及的方法中添加另一个参数,不如找出“this”中的当前方法是否已经在堆栈中。这可能吗?我可能会选择像ThreadLocal计数器这样的东西,在呼叫时增加它,在离开时减少它。通过这种方式,您可以分别计算它在每个线程上输入的时间。这也比扫描堆栈快得多。这也可以用于布尔值,仅用于递归检查 private ThreadLocal<int> _recursiveCounter = new
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结合起来。我有一个非常类似的问题,下面是我如何解决它的。基本上,我传递一个HashSet并尝试将其添加到这个对象中。如果已添加,则尚未处理此问题
// 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>());
}
}
可能有兴趣。也许你可以使用lock和Monitor.IsEntered来检测这种情况…@Johnny在同一个线程上,锁是无用的。我不是说锁定,而是检测递归…我在实现深度复制算法时遇到了一个非常类似的问题。当您开始遍历该结构时,请传递一个HashSet并将该对象添加到此HashSet中。当您开始进一步深入结构时,尝试将当前对象添加到HashSet中,如果添加失败,这意味着您进入了一个循环。尽管如此简单且性能卓越,留下痕迹绝对是解决问题的方法。如果我理解得很好,那么通过堆栈是不可能的,因为只有方法,但不能从帧中检索对象id。最后,我添加了一个堆栈变量,该变量记录了方法及其参数的指纹,效果非常好。我将把这个标记为一个答案,因为它启发了解决方案,谢谢@Lajos,我想你说的是StackFrame类。无论如何,使用它是不可行的。因为信息可能会通过内联等方式进行优化,而且从一开始就很难使用。顺便说一句,我认为,这个问题类似于谷歌面试的问题:在有限的硬件资源下,你能说出一个任意的单链接链,如果它包含一个循环吗?我认为这个方法的关键是你应该使用ThreadLocal,这样你就可以确定它是同一根线。所以是同一个堆栈