我编写了一个 logger/exceptionfactory 模块,它使用 System.Diagnostics.StackTrace 从调用方法及其声明类型中获取属性。但是我注意到,如果我在 Release模式下在 Visual Studio 之外运行代码,我的一些较短的方法会内联并从堆栈跟踪中丢失。现在我没有办法测试一个方法是否会在运行时内联,但我不想 [MethodImpl(MethodImplOptions.NoInlining)]
每个重要的方法。但是,如果我的基类中的某个方法因此而丢失,我可能会误读层和操作信息,这可能会导致错误的日志或错误参数化的异常。
是否有经验法则在何时何地内联什么?虚方法、静态方法、基类方法是否有区别对待?我只需要担心在程序集中内联吗?内部命名空间?
最佳答案
是的,有一些规则,但它们是 JIT 编译器使用的启发式方法,这些启发式方法可能会随时更改。
- 不能内联虚方法。
- 另一方面,接口(interface)方法可能是内联的,尽管我不能 100% 确定这是否会折叠堆栈跟踪。
- 当然可以内联静态方法和非虚拟实例方法。
- 内联可能会跨越 namespace (当然)和程序集(不那么明显),因为它发生在运行时,即 JIT 编译方法调用时。
- “重”方法不会被内联。这取决于“重”的定义,并且是 JIT 应用的启发式方法的一部分。
我所知道的“重”的一些启发式:
- 使用异常处理(即 try-catch 或 try-finally block )的方法不是内联的。
- 具有大代码(~32 IL 字节但我可能记错了)的方法未内联。
- 带有循环的方法不是内联的(除非循环可以完全展开或消除)。
关于c# - 用于登录 .NET 的堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4849709/