2010-04-16 4 views
265

Я знаю, вы можете сделатьКак получить имя текущего метода из кода

this.GetType().FullName 

Чтобы получить

My.Current.Class 

Но что я могу позвонить, чтобы получить

My.Current.Class.CurrentMethod 
+9

'this.ToString()' дает вам текущее имя класса только в том случае, если вы не сделали ничего особенного в своей собственной 'public override string ToString()'. 'GetType(). FullName' всегда дает вам полное имя. –

+0

@Pasi спасибо, изменит мою реализацию –

+3

В .Net 4.5 вы можете использовать CallerMemberNameAttribute, чтобы получить имя вызывающего. См. Https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx ... Затем вы можете обернуть тело своей функции анонимной функцией как in ([CallerMemberName] string functionName = "") => {}. Проблемы с использованием метода отражения, как и в принятом ответе, заключаются в том, что (1) функция может быть встроена, и/или (2) имя функции может быть запутано, если оно не является общедоступным, а код запутан. – GreatAndPowerfulOz

ответ

268
StackTrace st = new StackTrace(); 
StackFrame sf = st.GetFrame (0); 

MethodBase currentMethodName = sf.GetMethod(); 

Или, если вы хотите иметь вспомогательный метод:

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

    return sf.GetMethod().Name; 
} 

Изменено кредиты на @stusmith.

+52

Помните, что JIT свободен для встроенных методов, которые могут отбросить это. Чтобы заставить метод не быть встроенным, добавьте атрибут [MethodImpl (MethodImplOptions.NoInlining)]. – stusmith

+0

@stusmith: Спасибо! Вспомни это! – 2010-04-16 11:33:18

+0

@stusmith Спасибо –

415

Позвоните System.Reflection.MethodBase.GetCurrentMethod().Name изнутри способ.

+3

Это связано с инкрустацией? – Gusdor

+1

Если вам интересно, какой из них быстрее, Reflection или StackTrace проверьте это: https://stackoverflow.com/a/1348853/495455 –

+9

Чтобы сэкономить ваше время на ссылку выше: StackTrace работает быстрее. – lll

9

Вы также можете использовать MethodBase.GetCurrentMethod(), который будет препятствовать компилятору JIT от встраивания метода, в котором он используется.


Update:

Этот метод содержит специальный перечень 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 
+0

У вас есть ссылка, объясняющая, как метод GetCurrentMethod запрещает JIT с помощью встроенного метода вызова? – LukeH

+0

@ Luke, я обновил свой ответ по той причине, почему я считаю, что метод будет препятствовать встраиванию. –

+0

Спасибо, это очень интересно, хотя мне не совсем ясно, предотвращает ли он inlining метода, объявляющего локальный 'StackCrawlMark' или вызывающий объект этого метода. – LukeH

65

Отражение имеет умение скрывать лес за деревьями. Вы никогда не имеют проблем с получением имя текущего метода быстро и точно:

void MyMethod() { 
    string currentMethodName = "MyMethod"; 
    //etc... 
} 

Albeit что инструмент рефакторинга, вероятно, не будет исправить это автоматически.

Если вы полностью не волнует (значительного) стоимости с помощью отражения, этот вспомогательный метод должен быть полезен:

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; 
} 

Обновление: C# версии 5 и .NET 4.5 имеют золотой решение этой общей потребности, вы можете использовать [CallerMemberName] attribute, чтобы компилятор автоматически сгенерировал имя вызывающего метода в строчном аргументе. Другими полезными атрибутами являются [CallerFilePath], чтобы компилятор сгенерировал путь к файлу исходного кода и [CallerLineNumber], чтобы получить номер строки в файле исходного кода для оператора, сделавшего вызов.


Update2: синтаксис я предложил в верхней части ответа теперь можно заставить работать в C# версии 6 без фантазии инструмента рефакторинга:

string currentMethodName = nameof(MyMethod); 
+0

Я делал это раньше. Может быть дерн, чтобы поддерживать, если вы делаете это приложение, но в противном случае: простое умение в любой день! –

+2

Истинные слова, это примерно в 10 000 раз быстрее, дайте или возьмите коэффициент 10. –

+12

+1 для подсказки [CallerMemberNameAttribute] .NET 4.5. Благодарю. –

4

Ну System.Reflection.MethodBase.GetCurrentMethod().Name не очень хороший выбор, потому что будет просто отображать имя метода без дополнительной информации.

Возможно, для string MyMethod(string str) вышеуказанное свойство вернет MyMethod, что вряд ли подходит.

Лучше использовать System.Reflection.MethodBase.GetCurrentMethod().ToString(), которая будет возвращать весь метод подписи ...

+0

Я получаю MoveNext вместо моего имени метода. –

23

Я думаю, что лучший способ получить полное имя:

this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name; 

или попробовать этот

string method = string.Format("{0}.{1}", MethodBase.GetCurrentMethod().DeclaringType.FullName, MethodBase.GetCurrentMethod().Name); 
+0

+1, потому что использование отражения на несколько порядков быстрее, чем использование StackTrace. –

+4

Это не работает для методов 'async'. Я вызываю 'System.Reflection.MethodBase.GetCurrentMethod(). Name' в первой строке метода, и я получаю' MoveNext'. – Gusdor

+1

Возможно ли создать функцию, которая будет возвращать вызывающим функциям класс/имя? Ваше решение отлично, но немного долго называть каждый раз.Было бы идеально, если это может быть на какой-то другой класс и публичной функции или, возможно, на публичном свойстве, которое можно назвать. Идеально в каком-то статическом классе. – FrenkyB

Смежные вопросы