Can you use reflection to find the name of the currently executing method?

.NetReflection

.Net Problem Overview


Like the title says: Can reflection give you the name of the currently executing method.

I'm inclined to guess not, because of the Heisenberg problem. How do you call a method that will tell you the current method without changing what the current method is? But I'm hoping someone can prove me wrong there.

Update:

  • Part 2: Could this be used to look inside code for a property as well?
  • Part 3: What would the performance be like?

Final Result
I learned about MethodBase.GetCurrentMethod(). I also learned that not only can I create a stack trace, I can create only the exact frame I need if I want.

To use this inside a property, just take a .Substring(4) to remove the 'set_' or 'get_'.

.Net Solutions


Solution 1 - .Net

For non-async methods one can use

System.Reflection.MethodBase.GetCurrentMethod().Name;

https://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.getcurrentmethod

Please remember that for async methods it will return "MoveNext".

Solution 2 - .Net

As of .NET 4.5, you can also use [CallerMemberName].

Example: a property setter (to answer part 2):

protected void SetProperty<T>(T value, [CallerMemberName] string property = null)
{
    this.propertyValues[property] = value;
    OnPropertyChanged(property);
}

public string SomeProperty
{
    set { SetProperty(value); }
}

The compiler will supply matching string literals at call sites, so there is basically no performance overhead.

Solution 3 - .Net

The snippet provided by Lex was a little long, so I'm pointing out the important part since no one else used the exact same technique:

string MethodName = new StackFrame(0).GetMethod().Name;

This should return identical results to the MethodBase.GetCurrentMethod().Name technique, but it's still worth pointing out because I could implement this once in its own method using index 1 for the previous method and call it from a number of different properties. Also, it only returns one frame rather then the entire stack trace:

private string GetPropertyName()
{  //.SubString(4) strips the property prefix (get|set) from the name
    return new StackFrame(1).GetMethod().Name.Substring(4);
}

It's a one-liner, too ;)

Solution 4 - .Net

Try this inside the Main method in an empty console program:

MethodBase method = MethodBase.GetCurrentMethod();
Console.WriteLine(method.Name);

Console Output:
Main

Solution 5 - .Net

Comparing ways to get the method name -- using an arbitrary timing construct in LinqPad:

CODE
void Main()
{
	// from http://blogs.msdn.com/b/webdevelopertips/archive/2009/06/23/tip-83-did-you-know-you-can-get-the-name-of-the-calling-method-from-the-stack-using-reflection.aspx
	// and https://stackoverflow.com/questions/2652460/c-sharp-how-to-get-the-name-of-the-current-method-from-code
	
	var fn = new methods();
	
	fn.reflection().Dump("reflection");
	fn.stacktrace().Dump("stacktrace");
	fn.inlineconstant().Dump("inlineconstant");
	fn.constant().Dump("constant");
	fn.expr().Dump("expr");
	fn.exprmember().Dump("exprmember");
	fn.callermember().Dump("callermember");
	
	new Perf {
		{ "reflection", n => fn.reflection() },
		{ "stacktrace", n => fn.stacktrace() },
		{ "inlineconstant", n => fn.inlineconstant() },
		{ "constant", n => fn.constant() },
		{ "expr", n => fn.expr() },
		{ "exprmember", n => fn.exprmember() },
		{ "callermember", n => fn.callermember() },
	}.Vs("Method name retrieval");
}

// Define other methods and classes here
class methods {
	public string reflection() {
		return System.Reflection.MethodBase.GetCurrentMethod().Name;
	}
	public string stacktrace() {
		return new StackTrace().GetFrame(0).GetMethod().Name;
	}
	public string inlineconstant() {
		return "inlineconstant";
	}
	const string CONSTANT_NAME = "constant";
	public string constant() {
		return CONSTANT_NAME;
	}
	public string expr() {
		Expression<Func<methods, string>> ex = e => e.expr();
		return ex.ToString();
	}
	public string exprmember() {
		return expressionName<methods,string>(e => e.exprmember);
	}
	protected string expressionName<T,P>(Expression<Func<T,Func<P>>> action) {
		// https://stackoverflow.com/a/9015598/1037948
		return ((((action.Body as UnaryExpression).Operand as MethodCallExpression).Object as ConstantExpression).Value as MethodInfo).Name;
	}
	public string callermember([CallerMemberName]string name = null) {
		return name;
	}
}
RESULTS

reflection reflection

stacktrace stacktrace

inlineconstant inlineconstant

constant constant

expr e => e.expr()

exprmember exprmember

callermember Main

Method name retrieval: (reflection) vs (stacktrace) vs (inlineconstant) vs (constant) vs (expr) vs (exprmember) vs (callermember) 

 154673 ticks elapsed ( 15.4673 ms) - reflection
2588601 ticks elapsed (258.8601 ms) - stacktrace
   1985 ticks elapsed (  0.1985 ms) - inlineconstant
   1385 ticks elapsed (  0.1385 ms) - constant
1366706 ticks elapsed (136.6706 ms) - expr
 775160 ticks elapsed ( 77.516  ms) - exprmember
   2073 ticks elapsed (  0.2073 ms) - callermember
 

>> winner: constant

Note that the expr and callermember methods aren't quite "right". And there you see a repetition of a related comment that reflection is ~15x faster than stacktrace.

Solution 6 - .Net

Yes definitely.

If you want an object to manipulate I actually use a function like this:

public static T CreateWrapper<T>(Exception innerException, params object[] parameterValues) where T : Exception, new()
{
    if (parameterValues == null)
    {
        parameterValues = new object[0];
    }

    Exception exception   = null;
    StringBuilder builder = new StringBuilder();
    MethodBase method     = new StackFrame(2).GetMethod();
    ParameterInfo[] parameters = method.GetParameters();
    builder.AppendFormat(CultureInfo.InvariantCulture, ExceptionFormat, new object[] { method.DeclaringType.Name, method.Name });
    if ((parameters.Length > 0) || (parameterValues.Length > 0))
    {
        builder.Append(GetParameterList(parameters, parameterValues));
    }

    exception = (Exception)Activator.CreateInstance(typeof(T), new object[] { builder.ToString(), innerException });
    return (T)exception;
}

This line:

MethodBase method     = new StackFrame(2).GetMethod();

Walks up the stack frame to find the calling method then we use reflection to obtain parameter information values passed to it for a generic error reporting function. To get the current method simply use current stack frame (1) instead.

As others have said for the current methods name you can also use:

MethodBase.GetCurrentMethod()

I prefer walking the stack because if look internally at that method it simply creates a StackCrawlMark anyway. Addressing the Stack directly seems clearer to me

Post 4.5 you can now use the [CallerMemberNameAttribute] as part of the method parameters to get a string of the method name - this may help in some scenarios (but really in say the example above)

public void Foo ([CallerMemberName] string methodName = null)

This seemed to be mainly a solution for INotifyPropertyChanged support where previously you had strings littered all through your event code.

Solution 7 - .Net

EDIT: MethodBase is probably a better way to just get the method you're in (as opposed to the whole calling stack). I'd still be concerned about inlining however.

You can use a StackTrace within the method:

StackTrace st = new StackTrace(true);

And the look at the frames:

// The first frame will be the method you want (However, see caution below)
st.GetFrames();

However, be aware that if the method is inlined, you will not be inside the method you think you are. You can use an attribute to prevent inlining:

[MethodImpl(MethodImplOptions.NoInlining)]

Solution 8 - .Net

The simple way to deal is:

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

If the System.Reflection is included in the using block:

MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + MethodBase.GetCurrentMethod().Name;

Solution 9 - .Net

For Async Methods, you can use:

//using System.Reflection;

var myMethodName = MethodBase
                    .GetCurrentMethod()
                    .DeclaringType
                    .Name
                    .Substring(1)
                    .Split('>')[0];

Solution 10 - .Net

How about this:

StackFrame frame = new StackFrame(1);
frame.GetMethod().Name; //Gets the current method name

MethodBase method = frame.GetMethod();
method.DeclaringType.Name //Gets the current class name

Solution 11 - .Net

A bit more resilient, solution for customers from 2021,2022:

namespace my {
   public struct notmacros
   {

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string 
  whoami( [CallerMemberName] string caller_name = null)
  {
     if (string.IsNullOrEmpty(caller_name)) 
        return "unknown";
     if (string.IsNullOrWhiteSpace(caller_name)) 
        return "unknown";
     return caller_name;
  }
 }
} // my namespace

Usage

using static my.notmacros
 // somewhere  appropriate
 var my_name = whoami() ;

.NET fiddle link for the actual demo:

https://dotnetfiddle.net/moK73n

Please note the compiler requirement: .NET 6

Solution 12 - .Net

To handle both async and plain old method calls, I did this.

In my application, it's only getting called from exception handlers, so perf is not a concern.

[MethodImpl(MethodImplOptions.NoInlining)]
public static string GetCurrentMethodName()
{
	var st = new StackTrace();
	var sf = st.GetFrame(1);
	string name = sf.GetMethod().Name;

	if (name.Equals("MoveNext"))
	{
		// We're inside an async method
		name = sf.GetMethod().ReflectedType.Name
				 .Split(new char[] { '<', '>' }, StringSplitOptions.RemoveEmptyEntries)[0];
	}

	return name;
}

Solution 13 - .Net

I think you should be able to get that from creating a StackTrace. Or, as @edg and @Lars Mæhlum mention, MethodBase.GetCurrentMethod()

Solution 14 - .Net

I just did this with a simple static class:

using System.Runtime.CompilerServices;
.
.
.
public static class MyMethodName
{
    public static string Show([CallerMemberName] string name = "")
    {
        return name;
    }
}

then in your code:

private void button1_Click(object sender, EventArgs e)
{
    textBox1.Text = MyMethodName.Show();
}

private void button2_Click(object sender, EventArgs e)
{
    textBox1.Text = MyMethodName.Show();
}

Solution 15 - .Net

using System;
					
public class Program
{
	public static void Main()
	{
		
		Console.WriteLine("1: {0} {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, System.Reflection.MethodBase.GetCurrentMethod().ReflectedType);
		OtherMethod();
	}
	
	public static void OtherMethod()
	{
		Console.WriteLine("2: {0} {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, System.Reflection.MethodBase.GetCurrentMethod().ReflectedType);
	}
}

Output:

1: Main Program
2: OtherMethod Program

Solution 16 - .Net

Add this method somewhere and call it without parameter!

public static string GetCurrentMethodName([System.Runtime.CompilerServices.CallerMemberName] string name = "")
{
    return name;
}

Solution 17 - .Net

Try this...

    /// <summary>
    /// Return the full name of method
    /// </summary>
    /// <param name="obj">Class that calls this method (use Report(this))</param>
    /// <returns></returns>
    public string Report(object obj)
    {
        var reflectedType = new StackTrace().GetFrame(1).GetMethod().ReflectedType;
        if (reflectedType == null) return null;

        var i = reflectedType.FullName;
        var ii = new StackTrace().GetFrame(1).GetMethod().Name;

        return string.Concat(i, ".", ii);
    }

Solution 18 - .Net

new StackTrace().ToString().Split("\r\n",StringSplitOptions.RemoveEmptyEntries)[0].Replace("at ","").Trim()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoel CoehoornView Question on Stackoverflow
Solution 1 - .NetEd GuinessView Answer on Stackoverflow
Solution 2 - .NetJohn NilssonView Answer on Stackoverflow
Solution 3 - .NetJoel CoehoornView Answer on Stackoverflow
Solution 4 - .NetLars MæhlumView Answer on Stackoverflow
Solution 5 - .NetdrzausView Answer on Stackoverflow
Solution 6 - .NetLexView Answer on Stackoverflow
Solution 7 - .Netdenis phillipsView Answer on Stackoverflow
Solution 8 - .NetSharKView Answer on Stackoverflow
Solution 9 - .NetUseme AlehosainiView Answer on Stackoverflow
Solution 10 - .NetjesalView Answer on Stackoverflow
Solution 11 - .NetChef GladiatorView Answer on Stackoverflow
Solution 12 - .NetPaul WilliamsView Answer on Stackoverflow
Solution 13 - .NetbdukesView Answer on Stackoverflow
Solution 14 - .Netmichael kosakView Answer on Stackoverflow
Solution 15 - .Netmr RView Answer on Stackoverflow
Solution 16 - .NetRomerik RousseauView Answer on Stackoverflow
Solution 17 - .NetAdriano Silva RibeiroView Answer on Stackoverflow
Solution 18 - .NetBaglay VyacheslavView Answer on Stackoverflow