获取对象调用层次结构

时间:2011-07-05 13:59:48

标签: c# function object methods stack-trace

假设我有3个班级:

class A {
   void do_A() {
      //Check object call hierarchy
    }
}
class B {
   void do_B() {
      A a;
      a.do_A();
    }
}
class C {
   void do_C() {
      B b;
      b.do_A();
    }
}

然后我打电话给:

C c;
c.do_C();

如何从A的do_A()中获取对象调用层次结构?

我的意思是我想在 a.do_A()中获取对象的引用(可以通过this轻松获得),对象的引用 b 调用 a.do_A(),以及调用 b.do_B()的对象 c 的引用。

我认为这应该是可能的,因为我可以通过调用堆栈获得调用层次结构,所以我确信我应该能够获得有关调用这些方法的对象的更多信息。

3 个答案:

答案 0 :(得分:12)

首先,你所描述的是一个糟糕的编程习惯。方法的行为应该取决于它的参数,不取决于谁调用它。一个方法应该是可靠的,这样你就知道无论是谁调用它都会得到相同的行为。

其次,你似乎有一种常见但错误的信念,即调用堆栈是一个真实的东西,告诉你来自哪里。这完全不是调用堆栈的目的,但对于调试方案,它肯定是有用的。调用堆栈的目的是告诉您您下次去哪里,而不是您来自哪里。现在,通常情况下,你下一步的地方也是你来自哪里。通常你可以根据你知道你下一步去哪里来推断你来自哪里,这一事实经常是有用的,但你不能依赖。允许调用堆栈仅包含 足够的信息以确定下一步的位置;它可以丢弃所有不必要的信息,以确定你下一步的去向。

第三,你似乎是常见但错误的信念,即调用堆栈是确定你下一步的唯一系统,因此,你来自哪里。他们不是。正如我们将在下一版本的C#和VB中看到的那样,异步控制完全离开“你来自哪里”离开“你下一步的地方”而根本不使用调用堆栈。

也许你可以告诉我们为什么你想要这些信息。可能有更好的方法来做你想做的事。

答案 1 :(得分:4)

  

我的意思是我想获得参考资料   a.do_A()中的对象(可以很容易   由此获得),参考   对象b,称为a.do_A(),和   调用的对象c的引用   b.do_B()。

     

我认为这应该是可能的,   因为我可以获得调用层次结构   有了调用堆栈,所以我相信我应该   能够获得更多信息   关于调用的对象   方法

一般来说,你要求的东西在.NET中是不可能的 - 即使在理论上也是如此。也许不直观地,即使对象上的实例方法处于执行中,也无法保证对象仍然存活。从本质上讲,CLR足够智能,可以识别传递给实例方法的隐藏this引用何时不再被取消引用。然后,当发生这种情况时,引用的对象可以变得有资格进行收集(当然,假设它不能通过其他根目录到达)。

作为必然结果,“调用对象”完全有可能死了,而它调用的方法仍在执行。在您的具体示例中,完全有可能bc(实际上这些变量引用的对象)不再存在 A.do_A()正在执行。

这当然意味着您在此过程中以任何形式查找的信息可能不再可用,并且“神奇”API不应该能够可靠地生成它。

我建议阅读Raymond Chen的文章:When does an object become available for garbage collection?以更好地理解这个问题:

  

对象可以符合条件   执行期间的集合   关于那个对象的方法。

如果您认为这与您的问题无关,请考虑该文章中的倒数第二段:

  

另一位顾客问:“有没有   获取对实例的引用的方法   在每个帧中被调用   堆? (静态方法除外)   当然。)“一位不同的客户问道   大致相同的问题,但在一个   不同的背景:“我想要我的方法   走向堆栈,如果它   调用者是OtherClass.Foo,我想   获取OtherClass.Foo的this对象   所以我可以查询其他属性   从它。“你现在已经足够了解了   自己回答这些问题。

答案 2 :(得分:1)

这是不可能的,如果A想要知道谁调用do_A,那么do_A必须定义参数object caller及其调用者传递正确对象的责任实例到参数。