IT:AD:NET:HowTo:Exception Handling

Summary

Andrew C. said yesterday that he still knows of people who don’t understand why the “less exception handling the better”.

My answer to him was to show this page.

Note that it doesn’t mean no exception handling – it just means that get out of the way, let the error bubble up to the Application layer – ie, the last layer before the UI layer, try/catch, HANDLE it (ie log it), sanitize, and rethrow a UI compatible one.

Unless you are actually going to handle it, do not rethrow, wrap, replace, or anything else that distorts the stack.

using System;
 
namespace XAct.Spikes.RaiseHell
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("GetOutOfTheWay");
            try { new ExceptionTester(ThrowMechanism.GetOutOfTheWay).Execute(); }
            catch { }
            Console.WriteLine("------------------------------------------------------------------------");
            Console.WriteLine("Passthru");
            try { new ExceptionTester(ThrowMechanism.PassThru).Execute(); }
            catch { }
            Console.WriteLine("------------------------------------------------------------------------");
            Console.WriteLine("Rethrow");
            try { new ExceptionTester(ThrowMechanism.Rethrow).Execute(); }
            catch { }
            Console.WriteLine("------------------------------------------------------------------------");
            Console.WriteLine("Wrap");
            try { new ExceptionTester(ThrowMechanism.Wrap).Execute(); }
            catch { }
            Console.WriteLine("------------------------------------------------------------------------");
            Console.ReadLine();
        }
    }
 
    public enum ThrowMechanism
    {
        GetOutOfTheWay,
        PassThru,
        Rethrow,
        Wrap
    }
    public class ExceptionTester
    {
        ThrowMechanism _mecanism { get; set; }
 
        public ExceptionTester(ThrowMechanism mecanism)
        {
            _mecanism = mecanism;
        }
 
        public void Execute()
        {
            try
            {
                Call1();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
        }
 
 
 
        public void Call1()
        {
            if (_mecanism == ThrowMechanism.GetOutOfTheWay)
            {
                Call2();
                return;
            }
 
            try
            {
                Call2();
            }
            catch (Exception ex)
            {
                switch (_mecanism)
                {
                    case ThrowMechanism.PassThru:
                        throw;
                    case ThrowMechanism.Rethrow:
                        throw ex;
                    case ThrowMechanism.Wrap:
                        throw new Exception("Wrap.Call1", ex);
                    default:
                        throw new ArgumentOutOfRangeException("Throw Type not defined.");
                }
            }
        }
 
        public void Call2()
        {
            if (_mecanism == ThrowMechanism.GetOutOfTheWay)
            {
                Call3();
                return;
            }
 
            try
            {
                Call3();
            }
            catch (Exception ex)
            {
                switch (_mecanism)
                {
                    case ThrowMechanism.PassThru:
                        throw;
                    case ThrowMechanism.Rethrow:
                        throw ex;
                    case ThrowMechanism.Wrap:
                        throw new Exception("Wrap.Call2", ex);
                    default:
                        throw new ArgumentOutOfRangeException("Throw Type not defined.");
                }
            }
        }
 
        public void Call3()
        {
            if (_mecanism == ThrowMechanism.GetOutOfTheWay)
            {
                Call4();
                return;
            }
            try
            {
                Call4();
            }
            catch (Exception ex)
            {
                switch (_mecanism)
                {
                    case ThrowMechanism.PassThru:
                        throw;
                    case ThrowMechanism.Rethrow:
                        throw ex;
                    case ThrowMechanism.Wrap:
                        throw new Exception("Wrap.Call3", ex);
                    default:
                        throw new ArgumentOutOfRangeException("Throw Type not defined.");
                }
            }
        }
 
 
        public void Call4()
        {
            if (_mecanism == ThrowMechanism.GetOutOfTheWay)
            {
                Call5();
                return;
            }
            try
            {
                Call5();
            }
            catch (Exception ex)
            {
                switch (_mecanism)
                {
                    case ThrowMechanism.PassThru:
                        throw;
                    case ThrowMechanism.Rethrow:
                        throw ex;
                    case ThrowMechanism.Wrap:
                        throw new Exception("Wrap.Call4", ex);
                    default:
                        throw new ArgumentOutOfRangeException("Throw Type not defined.");
                }
            }
        }
 
        public void Call5()
        {
            if (_mecanism == ThrowMechanism.GetOutOfTheWay)
            {
                Offend();
                return;
            }
            try
            {
                Offend();
            }
            catch (Exception ex)
            {
                switch (_mecanism)
                {
                    case ThrowMechanism.PassThru:
                        throw;
                    case ThrowMechanism.Rethrow:
                        throw ex;
                    case ThrowMechanism.Wrap:
                        throw new Exception("Wrap.Call5", ex);
                    default:
                        throw new ArgumentOutOfRangeException("Throw Type not defined.");
                }
            }
        }
 
 
 
        public void Offend()
        {
            int d = 0;
            int x = 10 / d;
        }
    }
}
 

The result is…

  GetOutOfTheWay
  Attempted to divide by zero.
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Offend() in d:\users\sky\d
  ocuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.
  ThrowInvestigation\Program.cs:line 203
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call5() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 175
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call4() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 148
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call3() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 120
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call2() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 92
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call1() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 64
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Execute() in d:\users\sky\
  documents\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes
  .ThrowInvestigation\Program.cs:line 49
  ------------------------------------------------------------------------
  Passthru
  Attempted to divide by zero.
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Offend() in d:\users\sky\d
  ocuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.
  ThrowInvestigation\Program.cs:line 203
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call5() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 187
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call4() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 160
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call3() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 132
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call2() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 105
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call1() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 77
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Execute() in d:\users\sky\
  documents\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes
  .ThrowInvestigation\Program.cs:line 49
  ------------------------------------------------------------------------
  Rethrow
  Attempted to divide by zero.
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call1() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 79
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Execute() in d:\users\sky\
  documents\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes
  .ThrowInvestigation\Program.cs:line 49
  ------------------------------------------------------------------------
  Wrap
  Wrap.Call1
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Call1() in d:\users\sky\do
  cuments\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes.T
  hrowInvestigation\Program.cs:line 81
     at XAct.Spikes.ThrowInvestigation.ExceptionTester.Execute() in d:\users\sky\
  documents\visual studio 2010\Projects\XAct.Spikes.ThrowInvestigation\XAct.Spikes
  .ThrowInvestigation\Program.cs:line 49
  ------------------------------------------------------------------------
  ^A