173

Possible Duplicate:
How can I find the method that called the current method?

I'd like to write a method which obtains the name of the calling method, and the name of the class containing the calling method.

Is it possible with C# reflection?

Community
  • 1
  • 1
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552

5 Answers5

445
public class SomeClass
{
    public void SomeMethod()
    {
        StackFrame frame = new StackFrame(1);
        var method = frame.GetMethod();
        var type = method.DeclaringType;
        var name = method.Name;
    }
}

Now let's say you have another class like this:

public class Caller
{
   public void Call()
   {
      SomeClass s = new SomeClass();
      s.SomeMethod();
   }
}

name will be "Call" and type will be "Caller".

UPDATE: Two years later since I'm still getting upvotes on this

In .NET 4.5 there is now a much easier way to do this. You can take advantage of the CallerMemberNameAttribute.

Going with the previous example:

public class SomeClass
{
    public void SomeMethod([CallerMemberName]string memberName = "")
    {
        Console.WriteLine(memberName); // Output will be the name of the calling method
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BFree
  • 102,548
  • 21
  • 159
  • 201
  • 10
    This is as good a solution as you can get, but you need to remember that this won't necessarily return the answer you expect in release builds unless you disable JIT method inlining. – Greg Beech Jun 23 '10 at 14:31
  • @Greg Beech: True. Not a problem here because I'd not use reflection in any type of release build in any case. – Billy ONeal Jun 23 '10 at 16:43
  • 7
    In the .NET 3.5 solution, you should add [MethodImpl(MethodImplOptions.NoInlining)] above SomeMethod to avoid inlining. Passing false to the constructor also prevents loading of file name / line data from PDB files, speeding up the construction of the StackTrace. – bart Feb 20 '13 at 00:44
  • 42
    +1 for updating the answer – Joshua Drake Jul 22 '13 at 19:45
  • 1
    +1 for the updated answer – BAD_SEED Feb 05 '14 at 14:46
  • in [this answer](http://stackoverflow.com/a/1206071/3104287) it is mentioned that using `StackFrame` is too slow? compared to `MethodBase.GetCurrentMethod().Name` What do you suggest? (By the way I'm using your edit in `CallerMemberName` which is pretty good thank you :) ) – JustADev Jun 07 '15 at 19:00
  • 13
    It's notable that with the `[CallerMemberName]` solution the compiler takes care of the whole thing so it's better for performance as there's no actual reflection at runtime. – Grochni Aug 24 '15 at 12:36
  • Upvote from me. Some of us are still on .Net 4 ... Yes I'm too cheap to upgrade VS. :P – Arvo Bowen Oct 16 '15 at 13:30
  • 5
    Warning: If you use the STACKFRAME suggestion from this answer you must be aware that the code can produce different results when run from DEBUG vs RELEASE mode. I would not recommend it as it was a nightmare to track this down. If you are still determined to use it then I recommend you read the information in this blog post: https://corengen.wordpress.com/2011/09/14/different-number-of-stack-frames-between-debug-and-release-builds/ – user2565663 Feb 23 '16 at 15:56
  • 35
    Too bad there's no `[CallerTypeName]` to get the declaring type of the calling method... – cube45 Jul 28 '16 at 07:57
  • @cube45 - this solution here seems to resolve that part of your problem http://stackoverflow.com/a/37885619/3504007 – Kraang Prime Dec 16 '16 at 06:22
  • Yeah, this is the same as passing the type in parameter. That's pretty verbose and error-prone IMHO. The idea would be to directly get the caller type name. – cube45 Dec 16 '16 at 14:02
  • Is it necessary to give the parameter a default value? – Mohammed Noureldin Nov 01 '17 at 12:07
  • Too bad `[CallerMemberName]` is incompatible with properties. The original solution works great, I’m able to find out who changed my property. – Soonts Sep 28 '19 at 00:50
22

You can use it by using the StackTrace and then you can get reflective types from that.

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

StackFrame callingFrame = stackFrames[1];
MethodInfo method = callingFrame.GetMethod();
Console.Write(method.Name);
Console.Write(method.DeclaringType.Name);
Aren
  • 54,668
  • 9
  • 68
  • 101
  • Related https://stackoverflow.com/questions/171970/how-can-i-find-the-method-that-called-the-current-method – Pakk Dec 12 '17 at 15:45
13

It's actually something that can be done using a combination of the current stack-trace data, and reflection.

public void MyMethod()
{
     StackTrace stackTrace = new System.Diagnostics.StackTrace();
     StackFrame frame = stackTrace.GetFrames()[1];
     MethodInfo method = frame.GetMethod();
     string methodName = method.Name;
     Type methodsClass = method.DeclaringType;
}

The 1 index on the StackFrame array will give you the method which called MyMethod

Kishore Sahasranaman
  • 4,013
  • 3
  • 24
  • 50
ckramer
  • 9,419
  • 1
  • 24
  • 38
7

Yes, in principe it is possible, but it doesn't come for free.

You need to create a StackTrace, and then you can have a look at the StackFrame's of the call stack.

Lucero
  • 59,176
  • 9
  • 122
  • 152
7

Technically, you can use StackTrace, but this is very slow and will not give you the answers you expect a lot of the time. This is because during release builds optimizations can occur that will remove certain method calls. Hence you can't be sure in release whether stacktrace is "correct" or not.

Really, there isn't any foolproof or fast way of doing this in C#. You should really be asking yourself why you need this and how you can architect your application, so you can do what you want without knowing which method called it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bishnu
  • 853
  • 7
  • 11
  • 1
    This is A. a debug build, and B. calls other assemblies. The time it takes to start up the other programs via System.Diagnostics.Process dwarfs anything incurred by using the StackFrame class. – Billy ONeal Jun 22 '10 at 20:35
  • 1
    I'm doing this for the purposes of autoconfiguration of a test suite. – Billy ONeal Jun 22 '10 at 20:36