获取对象调用层次结构

可以说我有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() ,以及对象c的引用,称为b.do_B( )

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

我的意思是我想在a.do_A()中获取对象的引用(可以通过这个方便地实现),对象b的引用调用a.do_A(),以及对象c的引用,称为b.do_B( )。

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

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

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

这意味着您所寻求的信息可能在此过程中不再以任何forms提供 ,并且没有“神奇”API应该能够可靠地生成它。

我建议阅读Raymond Chen的文章: 什么时候对象可用于垃圾收集? 更好地理解这个问题:

在该对象上执行方法期间,对象可以符合收集条件。

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

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

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

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

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

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

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