【发布时间】:2011-06-07 07:07:08
【问题描述】:
我在应用程序中观察到很多“堆栈内省”代码,它们通常隐含地依赖于它们的包含方法不被内联以确保其正确性。此类方法通常涉及调用:
MethodBase.GetCurrentMethodAssembly.GetCallingAssemblyAssembly.GetExecutingAssembly
现在,我发现围绕这些方法的信息非常混乱。我听说运行时不会内联调用 GetCurrentMethod 的方法,但我找不到任何相关文档。我曾多次在 StackOverflow 上看到过帖子,例如 this one,表明 CLR 没有内联跨汇编调用,但 GetCallingAssembly documentation 强烈表明并非如此。
还有饱受诟病的 [MethodImpl(MethodImplOptions.NoInlining)],但我不确定 CLR 是否认为这是“请求”或“命令”。
请注意,我从合同的角度询问内联资格,不是关于 JITter 的当前实现何时因为实现困难而拒绝考虑方法,或者关于当 JITter 在评估权衡后最终 选择 内联合格方法时。我读过this 和this,但他们似乎更关注最后两点(顺便提到了 MethodImpOptions.NoInlining 和“exotic IL 指令”,但这些似乎是作为启发式而不是作为义务)。
CLR 何时允许内联?
【问题讨论】:
-
"什么时候允许 CLR 内联?"我猜只要该属性不存在。
-
@CodeInChaos:所以你是说
Assembly.GetExecutingAssembly被破坏了,除非我们用[MethodImpl(MethodImpOptions.NoInlining)]装饰方法? -
这是一个很好的链接(不能回答你所有的问题......):blogs.msdn.com/b/vancem/archive/2008/08/19/…
-
嗯,听起来像一个规范错误:我理解这样做的技术上的便利性,但显然 GetCallingAssembly 和朋友永远不应该被指定为内联敏感......叹息 - 和 GetExecutingAssembly 的文档不根本不提内联!
-
不是您问题的答案,但从 Visual Studio 2012 开始,现在可以在编译器的帮助下使用 Caller Information 属性获取调用方方法/属性名称、其文件位置和行号,即不受 JIT 内联的影响。此外,与堆栈(帧创建和后续)检查相比,它的速度非常快。