Retrieving the calling method name from within a method
Solution 1
I don't think it can be done without tracing the stack. However, it's fairly simple to do that:
StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
Console.WriteLine(methodBase.Name); // e.g.
However, I think you really have to stop and ask yourself if this is necessary.
Solution 2
In .NET 4.5 / C# 5, this is simple:
public void PopularMethod([CallerMemberName] string caller = null)
{
// look at caller
}
The compiler adds the caller's name automatically; so:
void Foo() {
PopularMethod();
}
will pass in "Foo"
.
Solution 3
This is actually really simple.
public void PopularMethod()
{
var currentMethod = System.Reflection.MethodInfo
.GetCurrentMethod(); // as MethodBase
}
But be careful through, I'm a bit skeptical to if inlining the method has any effect. You can do this to make sure that the JIT compiler won't get in the way.
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
var currentMethod = System.Reflection.MethodInfo
.GetCurrentMethod();
}
To get the calling method:
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
// 1 == skip frames, false = no file info
var callingMethod = new System.Diagnostics.StackTrace(1, false)
.GetFrame(0).GetMethod();
}
Solution 4
Just pass in a parameter
public void PopularMethod(object sender)
{
}
IMO: If it's good enough for events it should be good enough for this.
Solution 5
I have often found my self wanting to do this, but have always ending up refactoring the design of my system so I don't get this "Tail wagging the dog" anti-pattern. The result has always been a more robust architecture.
Admin
Updated on July 05, 2022Comments
-
Admin almost 2 years
I have a method in an object that is called from a number of places within the object. Is there a quick and easy way to get the name of the method that called this popular method.
Pseudo Code EXAMPLE:
public Main() { PopularMethod(); } public ButtonClick(object sender, EventArgs e) { PopularMethod(); } public Button2Click(object sender, EventArgs e) { PopularMethod(); } public void PopularMethod() { //Get calling method name }
Within
PopularMethod()
I would like to see the value ofMain
if it was called fromMain
... I'd like to see "ButtonClick
" ifPopularMethod()
was called fromButtonClick
I was looking at the
System.Reflection.MethodBase.GetCurrentMethod()
but that won't get me the calling method. I've looked at theStackTrace
class but I really didn't relish running an entire stack trace every time that method is called. -
Admin about 15 yearsJohn Leidgren - That will get me the name "PopularMethod", but I want the name of the method that called PopularMethod.
-
Admin about 15 yearsSruly - Yes that is definitely an option, I was trying to do it without altering the method call. This would be my last resort option.
-
user1839201 about 15 yearsFor more info see: discuss.joelonsoftware.com/default.asp?dotnet.12.511358.10
-
Guvante about 15 yearsSystem.Diagnostics is the namespace of StackTrace, System.Reflection is the namespace of MethodBase.
-
Admin about 15 yearsJason - Thank you, I'm not sure how resource intensive the "StackTrace" method is, but this does get me what I'm looking for. This is just a debugging code block for me, this won't be going into production. Thank you again for your help !
-
jcollum about 15 yearsThis has code smell to me; maybe there's some issues with your OO design here that make you want to see who called your method. In that case maybe you've got a polymorphism break?
-
Sruly about 15 yearsUnless you are exposing this as a public API, why would you go through a hassle and use reflection if you can just do it this way? REmember KISS
-
Allen Rice about 15 yearsThis is the BEST answer, do not use reflection or other stuff, ID the caller via a parameter.
-
John Leidegren about 15 years@Scott Vercuski - It's an immensly expensive operation, if there's any way you can avoid this you really should. It way worse than throwing exceptions and that's bad. It's nice that it can be done, but it should not be misused.
-
Admin about 15 years@John Leidegren - Definitely ... this isn't going into production code, we're just doing some massive QA testing and getting some strange happenings, this is just to help figure out where things are going haywire. Thank you !
-
Andrew about 14 yearsThe just use .GetFrame(1) instead, right?
-
Raymond over 13 years+1 for the
MethodInlining.NoInlining
. BTW the false on the StackTrace .ctor invocation is redundant, isnt it? -
John Leidegren over 13 yearsI believe it did exhibit slightly better preformance if I didn't ask for the file information explicitly. Truth be told, it probably doesn't matter, the main reason why I did it like that, was because I didn't need the file information.
-
Feckmore over 11 yearsWhat are the performance consequences of this solution?
-
Marc Gravell over 11 years@Feckmore none whatsoever : the compiler adds it as a literal during compilation. It will be signifantly faster than anything like looking at StackTrace etc. basically it gets compiled as PopularMethod("CurrentMethodName")
-
Chris Moschini over 11 yearsIf you're looking for something like namespace/assembly info, passing a Type can be a better choice since the call may come from a static method.
-
Zarepheth over 10 yearsI've written code for many systems. Often developers want to track the method which is writing a log entry. The if the logging code requires manually passing the method name, this requires developer to enter the method name as text every time it calls the logging method. Now use this same logging method in many different parts of the program, and see what happens as methods are added, deleted, and renamed with many developers over a few years. Automating the passing of the caller's method name will greatly ease development and debugging.
-
john ktejik about 10 yearsI get an error saying Cannot find CallerMemberName. VS Express C# 2010
-
Marc Gravell about 10 years@user396483 you need to be targeting .NET 4.5 or above for the attribute to exist (although you can define it yourself), and you need to be using C# 5 for it to work in the way desired. VS Express 2013 is available and free
-
Battle over 2 yearsI needed this recently to create class for logging. I wanted to automatically insert the class name + method name when doing a Log() call. Only this solution works. I'd recommend using a for-loop and StackTrace.GetFrame (i) and check each frame's method name (I excluded "log" and "debug", so that it shows me the actual method I want to log). Also use
new StackTrace (2, false);
where 2 is the number of methods within your logger class (you don't want to log anyway) and 'false' is set to halfen performance costs (if you don't need file info).