views:

129

answers:

7

I have a section of code that looks like this:

try
{
  classVar = functionCall(input, sEnum.First);

  classVar = functionCall(input, sEnum.Second);

  classVar = functionCall(input, sEnum.Third);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}

However my exception dosent show which specific call it came from. The stack trace also only shows details from another class called from inside the function call.

The alternative way to wrap this is:

try
{
  classVar = functionCall(input, sEnum.First);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}
try
{
  classVar = functionCall(input, sEnum.Second);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}
try
{
  classVar = functionCall(input, sEnum.Thrid);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}

Though I think it is much less readable that the previous version.

Is there a pattern for wrapping the function calls or passing off the exceptions in such a way that i can later see where they came from while keeping the code readable?

+2  A: 

Add a try/catch inside the functioncall() method and debug.assert there as well. If you absolutely need to, you can re-throw the exception there to pass it up the chain to this bit of code.

David Stratton
+2  A: 

The line number in the stack trace will tell you which of the three were called.

sixlettervariables
+1  A: 

How about writing your own exception class that carries as part of its payload the enum value? You can also write the log message to be more descriptive so that you don't have to rely on the stack trace to be the sole source of information.

Lee
Can you provide a link/code to a example of how to do this?
JustSmith
Inherit from exception, follow the design guidelines, and add a public property that contains the enumeration value. http://msdn.microsoft.com/en-us/library/ms229014.aspx
sixlettervariables
+4  A: 

What you probably want to do is capture and show the exception stack trace in addition to just the string value of the exception.

You can do this by using the StackTrace property on the exception. This will let you see where the exception happened.

catch (Exception e) { 
    Console.WriteLine(e.StackTrace);
}

Sample of how to get it to print. I'm sure you can figure out how to integrate it in with your debug system.

Bryan McLemore
ex.ToString() in the OP should print the stack trace, as well as the exception's description.
Stacy Vicknair
A: 

This is a little naive but...

ExceptHandler<sEnum> h = new ExceptHandler<sEnum>();
try
{
  h.Step = sEnum.First;
  classVar = functionCall(input, sEnum.First);
  h.Step = sEnum.Second;
  classVar = functionCall(input, sEnum.Second);
  h.Step = sEnum.Third;
  classVar = functionCall(input, sEnum.Third);
}
catch (Exception ex)
{
  h.AssertException(ex.ToString());
}

ExceptHandler is basically an state machine that hold the actual state you're performing. You can define it as a base class an inherit from it for specific cases ...

Edited to make it more .NET like :)

Jorge Córdoba
`ExceptHandler` should be made more .Net-like and have it be `h.Step = sEnum.First`, rather than a `SetStep()` method.
sixlettervariables
A: 

While it may not be the most elegant solution, you can add another variable to keep track of what step you are on:

    int step = 0;
    try
    {
       classVar = functionCall(input, sEnum.First);
       step++;

      classVar = functionCall(input, sEnum.Second);
      step++;

      classVar = functionCall(input, sEnum.Third);
   }
   catch (Exception ex)
   {
      //examine the step variable here

      Debug.Assert(false, ex.ToString());
   }
TLiebe
A: 

functionCall() should probably re-throw an exception with more specific information. A custom exception type may or may not be used.

Alternatively, this pattern can provide re-use of exception handling logic at a slight loss in readability:

static void InvokeActionProtected( Action action, string description ) {
   try 
   {
     action();
   }
   catch(Exception) { /* use description value */ }
}

// call like this
InvokeActionProtected( 
   () => classVar = functionCall(input, sEnum.Third),
   "Initializing value three"
);
Ryan S