如何从代码中获取当前方法的名称

Nic*_*len 356 c# introspection

我知道你能做到

this.GetType().FullName
Run Code Online (Sandbox Code Playgroud)

要得到

My.Current.Class
Run Code Online (Sandbox Code Playgroud)

但是我能得到什么呢

My.Current.Class.CurrentMethod
Run Code Online (Sandbox Code Playgroud)

Jam*_*Ide 499

System.Reflection.MethodBase.GetCurrentMethod().Name从方法中调用.

  • 为了节省您到达上述链接的时间:StackTrace更快. (59认同)
  • 如果你想知道哪一个更快,那么Reflection或StackTrace检查一下:/sf/answers/94419741/ (5认同)
  • 这是否受到内联的影响? (4认同)
  • @Konrad在`StackTrace`中产生的结果明显慢得多。产生更快结果的唯一方案是将反射与没有进行比较。我使用BenchmarkDotNet测试了MethodBase.GetCurrentMethod()。Name和new StackFrame(0).GetMethod()。Name,其中反射平均使用1.5us,而StackTrace使用11.5us。 (3认同)
  • 只需确保将 [MethodImpl(MethodImplOptions.NoInlined)] 作为装饰器添加到调用此方法的方法中,否则它将不起作用。谢谢 (2认同)

小智 347

using System.Diagnostics;
...

var st = new StackTrace();
var sf = st.GetFrame(0);

var currentMethodName = sf.GetMethod();
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要一个帮助方法:

[MethodImpl(MethodImplOptions.NoInlining)]
public string GetCurrentMethod()
{
    var st = new StackTrace();
    var sf = st.GetFrame(1);

    return sf.GetMethod().Name;
}
Run Code Online (Sandbox Code Playgroud)

更新了@stusmith的学分.

  • 请记住,JIT可以自由使用内联方法,这可能会使其失效.要强制方法不被内联,请添加[MethodImpl(MethodImplOptions.NoInlining)]属性. (58认同)
  • 请注意,将`MethodImpl(MethodImplOptions.NoInlining)`添加到`GetCurrentMethod`只会阻止该方法被内联到其调用者中.它不会阻止调用方法本身被内联到它自己的调用者等等. (33认同)
  • C#版本6有新功能`nameof()`也可以用于此目的:`nameof(this.YourCurrentMethod);`[https://msdn.microsoft.com/en-us/library/dn986596.aspx] (https://msdn.microsoft.com/en-us/library/dn986596.aspx) (16认同)
  • 然后是CallerMemberNameAttribute http://stackoverflow.com/a/15310053/58768 (8认同)
  • 仅供参考,这不会编译为`sf.GetMethod()`不是字符串. (4认同)

Han*_*ant 96

反射有躲避森林为树木的诀窍.准确快速地获取当前方法名称永远不会有问题:

void MyMethod() {
  string currentMethodName = "MyMethod";
  //etc...
}
Run Code Online (Sandbox Code Playgroud)

虽然重构工具可能无法自动修复它.

如果你完全不关心使用Reflection的(相当大的)成本,那么这个辅助方法应该是有用的:

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Reflection;
//...

[MethodImpl(MethodImplOptions.NoInlining)]
public static string GetMyMethodName() {
  var st = new StackTrace(new StackFrame(1));
  return st.GetFrame(0).GetMethod().Name;
} 
Run Code Online (Sandbox Code Playgroud)

更新:C#版本5和.NET 4.5具有满足此常见需求的黄金解决方案,您可以使用[CallerMemberName]属性让编译器在字符串参数中自动生成调用方法的名称.其他有用的属性是[CallerFilePath]让编译器生成源代码文件路径,[CallerLineNumber]用于获取进行调用的语句的源代码文件中的行号.


Update2:我现在可以在答案的顶部提出的语法在C#版本6中工作,而不需要花哨的重构工具:

string currentMethodName = nameof(MyMethod);
Run Code Online (Sandbox Code Playgroud)

  • [CallerMemberNameAttribute] .NET 4.5提示+1.谢谢. (16认同)
  • C#版本6有新功能`nameof()`也可以用于此目的:`nameof(this.YourCurrentMethod);`[https://msdn.microsoft.com/en-us/library/dn986596.aspx] (https://msdn.microsoft.com/en-us/library/dn986596.aspx) (13认同)
  • 真实的话,它快了大约10,000倍,给出或取10倍. (3认同)
  • 在我看来,你的第二个答案应该是*第二个回复*和[不是编辑](http://meta.stackoverflow.com/a/314024/282105).现在你的第二个答案隐藏在一个大的回复中,读者可能会错过第二部分. (3认同)

Zak*_*ria 34

我认为获得全名的最佳方式是:

 this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name;
Run Code Online (Sandbox Code Playgroud)

或试试这个

string method = string.Format("{0}.{1}", MethodBase.GetCurrentMethod().DeclaringType.FullName, MethodBase.GetCurrentMethod().Name);   
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于`async`方法.我在方法的第一行调用`System.Reflection.MethodBase.GetCurrentMethod().Name`,我得到`MoveNext`. (13认同)
  • @FrenkyB - 在辅助函数上使用[CallerMemberName]属性. (2认同)

Orw*_*ile 11

这不起作用吗?

System.Reflection.MethodBase.GetCurrentMethod()
Run Code Online (Sandbox Code Playgroud)

返回表示当前正在执行的方法的MethodBase对象.

命名空间:System.Reflection

汇编:mscorlib(在mscorlib.dll中)

http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod.aspx

  • 不适用于“异步”方法 (2认同)

Joã*_*elo 9

您也可以使用MethodBase.GetCurrentMethod()它来阻止JIT编译器内联它所使用的方法.


更新:

这个方法包含一个特殊的枚举StackCrawlMark,根据我的理解,它将指定JIT编译器不应该内联当前方法.

这是我对与SSCLI中存在的枚举相关的评论的解释.评论如下:

// declaring a local var of this enum type and passing it by ref into a function 
// that needs to do a stack crawl will both prevent inlining of the calle and 
// pass an ESP point to stack crawl to
// 
// Declaring these in EH clauses is illegal; 
// they must declared in the main method body
Run Code Online (Sandbox Code Playgroud)


小智 5

好吧System.Reflection.MethodBase.GetCurrentMethod().Name不是一个很好的选择'因为它只会显示方法名称而无需其他信息.

就像string MyMethod(string str)上面的属性将返回只是MyMethod几乎不够.

最好使用System.Reflection.MethodBase.GetCurrentMethod().ToString()哪个将返回整个方法签名...

  • 我得到的是MoveNext,而不是我的方法名称. (2认同)