Using StackTrace to Inference a Caller Method

Edit: Warning. Now I understand that the following method is usually seen as a bad idea, because it creates hidden dependencies for the sake of looking neat.


I recently discovered that you can use StackTrace to display information about the calling method.

This allows you to create a seemingly "cool" API where you simply call a method without trying to pass any explicit parameters to it, and the method determines what to do based on StackTrace.

Is it really bad, and if so, why?

Example:

public class Cache {
  public Object CheckCache()
  {
    Object valueToReturn = null;
    string key = GenerateCacheKeyFromMethodPrototype(new StackTrace().GetFrame(1).GetMethod()); //frame 1 contains caller
    if(key is in cache) valueToReturn = itemFromCache;

    return valueToReturn;   
  }
}

public class Foo { 
  private static Cache cache = new Cache();

  public Blah MethodFoo(param1, param2...)
  {
    Blah valueToReturn = cache.CheckCache(); //seems cool!
    if(valueToReturn == null)
    {
      valueToReturn = result of some calculation;
      //populate cache
    }

    return valueToReturn;
  }
}

      

I'm sure there are errors in the above pseudocode, but you are getting my drift.


Edit: thanks for the answers.

+1


source to share


4 answers


There are two reasons why not do this:

  • He is slow
  • This creates a fragile solution.


If you want to do this, you are better off using a tool that supports aspect-oriented programming, such as Castle Dynamic Proxy.

+5


source


Another problem is that the compiler might "build" your method into the optimization process, for example.

void MethodA() {
    MethodB();
}

void MethodB() {
   foo();
}

      

becomes:

void MethodA() {
   foo();
}

      



This is obviously a problem, because the immediate caller for foo is Nolonger MethodB, but MethodA instead. There is an attribute you can put on your method to prevent it from inline:

[MethodImpl( ... NoInline )]

      

(I can't remember the exact parameter)

-Oisin

+4


source


This is bad because I cannot know what the function is doing when I call it. I cannot test the function, because my test will call it from another function, which may cause different behavior.

And that's bad, because now there is an "invisible" contract that I have to execute when I call the function. Not only do I have to ensure that the correct parameters are passed, but I also need to make sure that the current function has the correct name. What if I have to wrap the function call in an anonymous lambda function? All of a sudden, I changed the behavior of the program and I had no idea beforehand, so now I can spend the next day debugging why the program suddenly and magically broke.

What happens to overloaded functions? Do you distinguish between them? Functions with the same name but in different classes? Functions with "special" names such as constructor, finalizer, operators, or lambdas?

What about when the functions are built into the compiler?

+3


source


I don't like this at all. Why would you want to use all the possible ways to get the required state in the method itself? This is similar to the anti-dependency injection pattern. Do not go there.

+1


source







All Articles