2

Is it possible to determine the calling method name "Eat Pizza" in PostError? I guess I could pass "EatPizza" as one of the arguments, but that would require changes each time the method name changes (unnecessary maintenance). But then, I wasn't even able to find the method name "EatPizza" in the context of "EatPizza" (using stacktrace, getframe, getmethod).

public void EatPizza(Pizza p){
    if(p==null){ //A arbitrary made up error
        Utilities.PostError();
    }
    else{
        p.Slices -= 1;
    }
}

...

public void PostError(){
    //Basically posting to database the name of the method
    //Tried this, didn't work: (new StackTrace(true)).GetFrame(5).GetMethod().Name
    //Is it possible to determine the calling method name "Eat Pizza" in this context?
}

When I try different values (0 to StackTrace.FrameCount-1) in StackTrace.GetFrame, I get the following values, when I just want "EatPizza":

.ctor
ThreadStart
Main
_nExecuteAssembly
RunUsersAssemblyDebugInZone
sooprise
  • 22,657
  • 67
  • 188
  • 276
  • You know, throwing an exception will get you the stack trace, and is the recommended way of handling errors. Any reason you are not doing that ? You could call `PostError` in a catch block if needed. – driis Apr 14 '11 at 17:53
  • Only thing I notice is that you're passing 5 into GetFrame. I think you want 0 for the current frame and 1 for the previous frame. But I also assume you are using that as more of a demonstration of the type of thing you tried, not the literal code you tried. – SirPentor Apr 14 '11 at 17:58
  • @driis, ok, that looks good. I now have a method that takes an Exception argument and posts Exception.StackTrace. I like this solution :) – sooprise Apr 14 '11 at 18:02

2 Answers2

4

You were on the right track with creating a StackTrace object, but you seem to have misunderstood the argument to GetFrame. Frames are numbered from the bottom-most frame, so:

  • GetFrame(0) would return PostError
  • GetFrame(1) would return the caller of PostError

So just try this:

var trace = new StackTrace(true);
WriteToDB(trace.GetFrame(1).GetMethod().Name);

Personally, I would prefer to get the entire stack trace rather than just the caller, so I'd do this:

var trace = new StackTrace(true);
WriteToDB(trace.ToString());
JSBձոգչ
  • 40,684
  • 18
  • 101
  • 169
  • 1
    +1 If you're going to log errors with a partial trace, why not include the whole thing and gain the advantage of having the "big picture" at your disposal? – Pete M Apr 14 '11 at 18:00
  • +1, Yes, this all makes sense. The stack trace contains sufficient info for my error logging purposes, thanks! – sooprise Apr 14 '11 at 18:03
2

Is it possible to determine the calling method name "Eat Pizza" in PostError? I guess I could pass "EatPizza" as one of the arguments, but that would require changes each time the method name changes (unnecessary maintenance).

Calling PostError in all the methods in which something could go wrong is also "unnecessary maintenance". It also complicates the execution flow of your program, because you will have to check for errors all over the place, and high-level processes will have to check if the low level processes completed successfully.

It is better to use the exception handling structures provided by the CLR and C#.

The exact location in which the error occured is stored in the exception's StackTrace property.

pubic void BigDinnerEatingProcess()
{
    try
    {
         WhateverHappensAtTheTopLevel();
    }
    catch (PizzaNotDeliveredException ex)
    {
         Utilities.PostError(ex);
         MessageBox.Show("Dinner was not eaten. Please make sure the pizza is delivered.");
    }
}

public void EatPizza(Pizza p)
{
    if (p == null)
        throw new PizzaNotDeliveredException();
    p.RemoveOneSlice();
}

private void PostError(Exception ex)
{
    string errorLocation = ex.StackTrace;
    //...
}
Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
  • +1 for unnecessary complication. @sooprise What if you decided to refactor your logging method, and `StackTrace.GetFrame` ended up being 2 levels deep instead of 1 that it is now? You would then have to manually adjust for +1 frames all over your code. – bottlenecked Apr 14 '11 at 18:11