【问题标题】:Is it safe to use the StackTrace class to find the caller of the current method使用 StackTrace 类查找当前方法的调用者是否安全
【发布时间】:2026-01-24 08:40:01
【问题描述】:

我想知道使用以下代码来确定调用当前执行代码的方法或对象的名称(可能还有更多信息)是否安全:

StackTrace stackTrace = new StackTrace();           // get call stack
StackFrame[] stackFrames = stackTrace.GetFrames();  // get method calls (frames)

更具体地说,是否存在无法访问框架或引发异常的特殊/极端情况?

我查看了the MSDN page of StackTrace,但没有发现任何可能的问题。

【问题讨论】:

  • 堆栈跟踪不会识别您去过哪里,它会告诉您下一步要去哪里。
  • @liortal 如果您只需要方法名称并且可以等待 C# 4.5,您可以使用 CallerMemberNameAttribute
  • @AshBulaczenko:不,asawyer 完全正确。堆栈跟踪不会告诉您您来自哪里,它会告诉您您要去哪里。 这就是堆栈的目的。堆栈是运行时通过它知道当前方法完成时下一步要去哪里的机制。大多数时候,“你接下来要去哪里”和“你要去哪里”是一个令人高兴的意外。来自" 或多或少是同一个地方,但没有要求是这种情况,在 C# 5 中它会停止这种情况;异步代码不使用堆栈来确定下一步要去哪里。
  • @brgerner:没有 C# 4.5;它将是 C# 5。C# 和 Visual Basic 版本号与 CLR 版本号不匹配。
  • @liortal:没错。例如,假设该方法是尾递归。说static bool Contains(Link link, int x) { if (link == null) return false; if (link.Head == x) return true; return Contains(link.Tail, x); }。假设你传入一个有两个节点的链表。您会期望在第一次和第二次递归之后,堆栈跟踪显示调用者是Contains。但是 jit 编译器可以意识到 在最后一次调用 Contains 之后什么都没有发生,只是返回了它的值。 因此,jitter 完全可以将其重写为...

标签: c# .net callstack


【解决方案1】:

编译器可能会内联方法,提供与直接查看代码所期望的不同的视图。你可以使用一个属性来确保你的方法没有被内联:

[MethodImpl(MethodImplOptions.NoInlining)]
public void MyMethod() {
  // Get the stack trace.
}

否则,如果MyMethod 被内联,则堆栈跟踪不包含您的代码可能依赖的MyMethod 的框架。

【讨论】: