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