内联.Net方法时,属性会发生什么?

时间:2014-06-13 11:02:52

标签: .net inline

我在一个类中有一些代码,它爬行堆栈跟踪以查找其调用堆栈中方法的特定属性。

我注意到我的一个测试开始从自动构建失败,当时该测试总是从我的机器传递出来。当我深入研究它时,看起来有问题的代码在调试模式或发布模式下工作正常,只要你连接了调试器,但在没有调试器的发布模式下失败。

从我所看到的,我正在寻找的方法是内联,当发生这种情况时,该方法的属性就会丢失。

是这样的吗?属性是否会丢失?

这是一个重现我的问题的小应用程序:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;


namespace InliningAndAttributes
{

    public class SomeClass
    {

        [Description("Foo")]
        public void SomeMethodThatWillGetInlined()
        {
            SomeMethodThatWontGetInlined();
        }

        protected virtual void SomeMethodThatWontGetInlined()
        {
            var caller = FindDescribedCaller();
            Console.WriteLine("Could I find description attribute? {0}", caller != null);
        }

        private MethodBase FindDescribedCaller()
        {
            var callStack = new StackTrace();
            int frameIndex = 0;
            while (frameIndex++ <= callStack.FrameCount)
            {
                Console.WriteLine("Getting frame" + frameIndex);
                var currentFrame = callStack.GetFrame(frameIndex);
                if (currentFrame == null)
                {
                    continue;
                }
                var method = currentFrame.GetMethod();
                Console.WriteLine(method.Name);
                if (Attribute.IsDefined(method, typeof(DescriptionAttribute)))
                {
                    return method;
                }
            }
            return null;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var someClass = new SomeClass();
            someClass.SomeMethodThatWillGetInlined();

            Console.ReadLine();
        }
    }
}

当我在.Net 4.5下运行此应用程序时,使用Release版本并且没有附加调试器,我得到以下输出:

Getting frame1
SomeMethodThatWontGetInlined
Getting frame2
Main
Getting frame3
Getting frame4
Could I find description attribute? False

1 个答案:

答案 0 :(得分:6)

用户代码无法检测内联。如果它可能是一个破碎的编译器优化。优化是不可检测的(当然,除非它们利用未定义或未指定的行为)。

错误不是属性丢失。错误是您的代码依赖于运行时StackTrace,它确实具有未指定的内容。这是一个提供尽力而为数据的调试类。内联删除堆栈帧。

您可能不应该依赖于您的方法的调用者。 (不仅因为它不起作用,而且因为它非常脆弱而且不能自我记录)。寻找其他解决方案。通过传递一个额外的参数使调用者识别自己。