假设我有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 的引用。
我认为这应该是可能的,因为我可以通过调用堆栈获得调用层次结构,所以我确信我应该能够获得有关调用这些方法的对象的更多信息。
答案 0 :(得分:12)
首先,你所描述的是一个糟糕的编程习惯。方法的行为应该取决于它的参数,不取决于谁调用它。一个方法应该是可靠的,这样你就知道无论是谁调用它都会得到相同的行为。
其次,你似乎有一种常见但错误的信念,即调用堆栈是一个真实的东西,告诉你来自哪里。这完全不是调用堆栈的目的,但对于调试方案,它肯定是有用的。调用堆栈的目的是告诉您您下次去哪里,而不是您来自哪里。现在,通常情况下,你下一步的地方也是你来自哪里。通常你可以根据你知道你下一步去哪里来推断你来自哪里,这一事实经常是有用的,但你不能依赖。允许调用堆栈仅包含 足够的信息以确定下一步的位置;它可以丢弃所有不必要的信息,以确定你下一步的去向。
第三,你似乎是常见但错误的信念,即调用堆栈是确定你下一步的唯一系统,因此,你来自哪里。他们不是。正如我们将在下一版本的C#和VB中看到的那样,异步控制完全离开“你来自哪里”离开“你下一步的地方”而根本不使用调用堆栈。
也许你可以告诉我们为什么你想要这些信息。可能有更好的方法来做你想做的事。
答案 1 :(得分:4)
我的意思是我想获得参考资料 a.do_A()中的对象(可以很容易 由此获得),参考 对象b,称为a.do_A(),和 调用的对象c的引用 b.do_B()。
我认为这应该是可能的, 因为我可以获得调用层次结构 有了调用堆栈,所以我相信我应该 能够获得更多信息 关于调用的对象 方法
一般来说,你要求的东西在.NET中是不可能的 - 即使在理论上也是如此。也许不直观地,即使对象上的实例方法处于执行中,也无法保证对象仍然存活。从本质上讲,CLR足够智能,可以识别传递给实例方法的隐藏this
引用何时不再被取消引用。然后,当发生这种情况时,引用的对象可以变得有资格进行收集(当然,假设它不能通过其他根目录到达)。
作为必然结果,“调用对象”完全有可能死了,而它调用的方法仍在执行。在您的具体示例中,完全有可能b
和c
(实际上这些变量引用的对象)不再存在 而 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
及其调用者传递正确对象的责任实例到参数。