- In methods and functions throw exceptions, don't try and return -1's or nulls or empty strings, something went wrong let your system know through an exception.
- Don't bury exceptions, when an exception occurs it contains a lot of good information so when you catch one re throw it using just throw; otherwise you'll strip the stack trace and it'll be harder to figure out where's the source of your error.
- clean up your data, if an exception occurs clean the mess up.
and the xaml
<Page
x:Class="pc.exceptions.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:pc.exceptions"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Text="Exception Example"
Style="{ThemeResource HeaderTextBlockStyle}"
VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBox x:Name="Denominator_TXT"
Text="0" Width="100"
HorizontalAlignment="Left"/>
<Button x:Name="DivideByZero_BTN" Content="1/0
Exception" />
</StackPanel>
</Grid>
</Page>
and lets look at the code behind
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace pc.exceptions
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DivideByZero_BTN.Click += DivideByZero_BTN_Click;
}
//thrid
exception thrown
void DivideByZero_BTN_Click(object sender, RoutedEventArgs e)
{
var d = Convert.ToInt32(Denominator_TXT.Text);
try
{
var x = CalculateTwo(CalculateOne, 9, d);
}
catch (Exception ex)
{
//this
is bad, don't do this
throw ex;
}
}
//second
function to throw exception
double CalculateTwo(Func<int, int, double> CalculationFunc, int A, int B)
{
try
{
return CalculationFunc.Invoke(A, B);
}
catch (DivideByZeroException ex)
{
throw;
}
}
//First
Function to throw Exception
double CalculateOne(int a, int b)
{
try
{
return a / b;
}
catch (DivideByZeroException ex)
{
throw;
}
}
}
}
What we have is pretty straight forward, basically we create a divide by zero exception on purpose to trace the errors now when we run our app and cause our exception. lets inspect our exception stack trace at each level
CalculateOne
at pc.exceptions.MainPage.CalculateOne(Int32 a, Int32 b)
We see the original source of our exception
CalculateTwo
at pc.exceptions.MainPage.CalculateOne(Int32 a, Int32 b)
at pc.exceptions.MainPage.CalculateTwo(Func`3 CalculationFunc, Int32 A, Int32 B)
Now we can trace the original source of our exception
DivideByZero_BTN_Click
at pc.exceptions.MainPage.DivideByZero_BTN_Click(Object sender, RoutedEventArgs e)
we've lost our stack trace history, so by inspecting it at or after this level we can't really tell where the error originated from. however if we change
//thrid
exception thrown
void DivideByZero_BTN_Click(object sender, RoutedEventArgs e)
{
var d = Convert.ToInt32(Denominator_TXT.Text);
try
{
var x = CalculateTwo(CalculateOne, 9, d);
}
catch (Exception ex)
{
//this is bad, don't do this
throw ex;
}
}
//thrid
exception thrown
void DivideByZero_BTN_Click(object sender, RoutedEventArgs e)
{
var d = Convert.ToInt32(Denominator_TXT.Text);
try
{
var x = CalculateTwo(CalculateOne, 9, d);
}
catch (Exception ex)
{
//Much
better
throw;
}
}
at pc.exceptions.MainPage.CalculateOne(Int32 a, Int32 b)
at pc.exceptions.MainPage.CalculateTwo(Func`3 CalculationFunc, Int32 A, Int32 B)
at pc.exceptions.MainPage.DivideByZero_BTN_Click(Object sender, RoutedEventArgs e)
much better, this again allows us to trace our tack to see where the error actually originated from.
now you may have noticed that once our application runs out of opportunities to handle our exception our application catches it for the final time in debugger via the unhandled excption event
#pragma checksum "c:\users\administrator\documents\visual
studio 2013\Projects\pc.exceptions\pc.exceptions\App.xaml"
"{406ea660-64cf-4c82-b6f0-42d48172a799}"
"3D2BE5729E141535E26842E969B8DF4A"
//------------------------------------------------------------------------------
//
<auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect
behavior and will be lost if
// the code is regenerated.
//
</auto-generated>
//------------------------------------------------------------------------------
namespace pc.exceptions
{
#if !DISABLE_XAML_GENERATED_MAIN
public static class Program
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
static void Main(string[] args)
{
global::Windows.UI.Xaml.Application.Start((p) => new App());
}
}
#endif
partial class App : global::Windows.UI.Xaml.Application
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
private bool _contentLoaded;
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent()
{
if (_contentLoaded)
return;
_contentLoaded = true;
#if DEBUG &&
!DISABLE_XAML_GENERATED_BINDING_DEBUG_OUTPUT
DebugSettings.BindingFailed +=
(sender, args) =>
{
global::System.Diagnostics.Debug.WriteLine(args.Message);
};
#endif
#if DEBUG &&
!DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e)
=>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
}
}
}
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.UnhandledException += App_UnhandledException;
}
private void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//handle
excption
e.Handled = true;
}
There are exceptions that will terminate your application regardless if they're handled and of coarse when there's an exception you can no longer guarantee the state of your application and thus the best course of action may very well be to just shut it down.