English 中文(简体)
Pattern to catch exception from sections of code (while not making eyes bleed)
原标题:

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?

最佳回答

Option 1 Change functionCall() to re-throw a custom exception with contextual information. Catch the exception at a higher level for logging, calling Debug.Assert, etc.

Option 2 This pattern can provide reuse of exception handling logic at a slight loss in readability. Caution: over-use of delegate techniques at the cost of clarity can become a code smell.

static void InvokeActionWithContext(Action action, string description) {
   try 
   {
     action();
   }
   catch(Exception ex)
   {
     throw new AnExceptionWithContext(description, ex);
   }
}

// call like this
InvokeActionWithContext( 
   () => classVar = functionCall(input, sEnum.Third),
   "Initializing value three"
);
问题回答

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.

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.

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

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.

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());
   }

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 :)





相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签