如果我只是想看看我叫什么,

var st = new StackTrace();
var callingMethod = st.GetFrame(1).GetMethod()

买那种特殊的镜框会便宜吗?
var sf = new StackFrame(1);
var callingMethod = sf.GetMethod()

我用下面的代码进行了测试,但我不确定我的方法是否正确。
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
  var method = new StackFrame(1, false);
}
sw.Stop();
Trace.WriteLine(sw.ElapsedMilliseconds);

sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
  var method = new StackTrace().GetFrame(1);
}
sw.Stop();
Trace.WriteLine(sw.ElapsedMilliseconds);

// Results
// StackFrame: 850
// StackTrace: 1334

我的方法(和结果)正确吗?
编辑
我会使用Caller Information属性,但是,我暂时停留在.net 3.5中。

最佳答案

有关正确基准的编译,请参见recommendations。您应该使用基本迭代次数(用于抑制jitLoop unwinding优化)、在释放模式下运行基准测试而不进行调试、使用缓存预热等。
我在BenchmarkDotNet中添加了您的示例,查看StackFrameProgram.cs

public class StackFrameProgram
{
    private const int IterationCount = 100001;

    public void Run()
    {
        var competition = new BenchmarkCompetition();
        competition.AddTask("StackFrame", () => StackFrame());
        competition.AddTask("StackTrace", () => StackTrace());
        competition.Run();
    }

    private StackFrame StackFrame()
    {
        StackFrame method = null;
        for (int i = 0; i < IterationCount; i++)
            method = new StackFrame(1, false);
        return method;
    }

    private StackFrame StackTrace()
    {
        StackFrame method = null;
        for (int i = 0; i < IterationCount; i++)
            method = new StackTrace().GetFrame(1);
        return method;
    }
}

这是我的结果(Intel Core i7-3632qm CPU 2.20GHz):
x86, .NET 3.5:
StackFrame : 1035ms
StackTrace : 1619ms

x64, .NET 3.5:
StackFrame :  981ms
StackTrace : 1754ms

x86, .NET 4.0:
StackFrame :  735ms
StackTrace : 1150ms

x64, .NET 4.0:
StackFrame : 637ms
StackTrace : 880ms

让我们看看里面:
public StackFrame.ctor(int skipFrames, bool fNeedFileInfo)
{
    this.InitMembers();
    this.BuildStackFrame(skipFrames, fNeedFileInfo);
}

private void StackFrame.BuildStackFrame(int skipFrames, bool fNeedFileInfo)
{
    StackFrameHelper sfh = new StackFrameHelper(fNeedFileInfo, null);
    StackTrace.GetStackFramesInternal(sfh, 0, null);
    int numberOfFrames = sfh.GetNumberOfFrames();
    skipFrames += StackTrace.CalculateFramesToSkip(sfh, numberOfFrames);
    if ((numberOfFrames - skipFrames) > 0)
    {
        this.method = sfh.GetMethodBase(skipFrames);
        this.offset = sfh.GetOffset(skipFrames);
        this.ILOffset = sfh.GetILOffset(skipFrames);
        if (fNeedFileInfo)
        {
            this.strFileName = sfh.GetFilename(skipFrames);
            this.iLineNumber = sfh.GetLineNumber(skipFrames);
            this.iColumnNumber = sfh.GetColumnNumber(skipFrames);
        }
    }
}

public StackTrace.ctor()
{
    this.m_iNumOfFrames = 0;
    this.m_iMethodsToSkip = 0;
    this.CaptureStackTrace(0, false, null, null);
}

private void StackTrace.CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThread, Exception e)
{
    this.m_iMethodsToSkip += iSkip;
    StackFrameHelper sfh = new StackFrameHelper(fNeedFileInfo, targetThread);
    GetStackFramesInternal(sfh, 0, e);
    this.m_iNumOfFrames = sfh.GetNumberOfFrames();
    if (this.m_iMethodsToSkip > this.m_iNumOfFrames)
    {
        this.m_iMethodsToSkip = this.m_iNumOfFrames;
    }
    if (this.m_iNumOfFrames != 0)
    {
        this.frames = new StackFrame[this.m_iNumOfFrames];
        for (int i = 0; i < this.m_iNumOfFrames; i++)
        {
            bool flag = true;
            bool flag2 = true;
            StackFrame frame = new StackFrame(flag, flag2);
            frame.SetMethodBase(sfh.GetMethodBase(i));
            frame.SetOffset(sfh.GetOffset(i));
            frame.SetILOffset(sfh.GetILOffset(i));
            frame.SetIsLastFrameFromForeignExceptionStackTrace(sfh.IsLastFrameFromForeignExceptionStackTrace(i));
            if (fNeedFileInfo)
            {
                frame.SetFileName(sfh.GetFilename(i));
                frame.SetLineNumber(sfh.GetLineNumber(i));
                frame.SetColumnNumber(sfh.GetColumnNumber(i));
            }
            this.frames[i] = frame;
        }
        if (e == null)
        {
            this.m_iMethodsToSkip += CalculateFramesToSkip(sfh, this.m_iNumOfFrames);
        }
        this.m_iNumOfFrames -= this.m_iMethodsToSkip;
        if (this.m_iNumOfFrames < 0)
        {
            this.m_iNumOfFrames = 0;
        }
    }
    else
    {
        this.frames = null;
    }
}

public virtual StackFrame StackTrace.GetFrame(int index)
{
    if (((this.frames != null) && (index < this.m_iNumOfFrames)) && (index >= 0))
    {
        return this.frames[index + this.m_iMethodsToSkip];
    }
    return null;
}

07-28 03:04