.net MethodBase.GetCurrentMethod何时可靠/可预测?

.net MethodBase.GetCurrentMethod何时可靠/可预测?,.net,clr,jit,inlining,.net,Clr,Jit,Inlining,方法可以内联;有一个属性可以防止这种情况(“有一个att用于此”)。然而,显然,由于抖动()的尾部调用优化,方法也可能无法在x64上获得自己的堆栈帧。这会影响MethodBase.GetCurrentMethod的行为吗 我能找到的讨论主要是关于内联()。虽然这些讨论本身很有趣,但我的问题实际上是关于在什么情况下(如果有的话)MethodBase.GetCurrentMethod可以用来识别程序员调用的同一方法(例如,对于当前方法实际上是代理的方法的后期绑定)。内联是MethodBase.Get

方法可以内联;有一个属性可以防止这种情况(“有一个att用于此”)。然而,显然,由于抖动()的尾部调用优化,方法也可能无法在x64上获得自己的堆栈帧。这会影响MethodBase.GetCurrentMethod的行为吗


我能找到的讨论主要是关于内联()。虽然这些讨论本身很有趣,但我的问题实际上是关于在什么情况下(如果有的话)
MethodBase.GetCurrentMethod
可以用来识别程序员调用的同一方法(例如,对于当前方法实际上是代理的方法的后期绑定)。内联是
MethodBase.GetCurrentMethod
可能会被愚弄的一种方式,但我想知道它是否是唯一的方式?

否-方法要么在运行时内联,要么不是

我相信,如果有人实现了自己的运行时——如
MethodBase。GetCurrentMethod
最终归结为这一点,在
RuntimeMethodHandle
中声明:

[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern IRuntimeMethodInfo 
  _GetCurrentMethod(ref StackCrawlMark stackMark);
在自定义运行时中,它可以做任何事情——将来它也可以做任何事情。目前,我相信Microsoft运行时不会返回正确方法的唯一方法是如果代码是内联的;例如,不能代表单声道说话。然而,我认为,依赖于这种情况就像依赖于一个内部类型的反射私有字段总是存在以使一段代码能够工作一样

在几乎所有我尝试过(现在我不再担心)或有人试图证明需要可靠地识别调用方法的情况下,除了评测之外,内联方法的问题总是会出现

然而,现实是,担心这些方法有多重要


如果可靠性是绝对重要的,那么使用IL重写器编译后注入日志调用会更幸运;这可能是有方法意识的,因此可能会破坏内联,即使它发生了(如果重写的IL变得足够大,可能不会破坏性能)。或者,如果您不喜欢使用自己的AOP库,可能需要一个AOP库—例如。

尾部调用优化并不是这样做的,它只是将递归调用重写为for循环。方法总是有一个堆栈框架,这是代码安全和异常所必需的。当一个方法内联时,您只需获取调用方方法的名称。请注意,GetCurrentMethod非常昂贵,并且不能简单地在代码中编写方法名。这本身也解决了内联问题。@Hans,以下是我在x64上发现的关于尾部调用优化的内容:。您的评论可能站得住脚,但在那个例子中,我们并不是在看递归。在我的后期绑定场景中,代理项构造并缓存一个动态委托,以便对代理项的后续调用不需要再次反映。因此,性能不是主要考虑因素;而是可靠性(如果重命名方法,在代码中嵌入方法名称容易出现可靠性问题)。我突然想到:我不需要
GetCurrentMethod
(不可靠),也不需要将方法名称作为字符串嵌入代码中(不会自动处理键入或重命名)。相反,我可以嵌入一个调用该方法的表达式。一段时间以来,我一直在做这方面的财产参考;我不知道为什么我花了这么长时间才考虑将同样的技术应用到方法上,我的问题其实不是内联。内联只是我所知道的
MethodBase.GetCurrentMethod
可能被愚弄的一种方法。我的问题是:
MethodBase.GetCurrentMethod
是否还有其他方法可以被愚弄(即,识别一个不同于程序员调用的方法)。好吧,JIT内联可能不是唯一的方法-正如我更新的答案所示,目前,MS运行时可能只能通过内联来愚弄它,但对于未来,以及其他运行时,谁知道呢。最好不要依赖任何特定的行为。事实上,根据你的定义,任何IL重写器都可以实现这种行为,如果你说的是开发人员调用的位置和调用实际结束的位置之间的不同。