19Aug/100
Extending exceptions
Sometimes you have a function which needs to communicate back on failure through special exceptions as you want to program have the option to fix certain functions. For example a formula whose input parameter is bad (example: begin date is after the end date) or when the database throws up or anything.
Now you could do the following:
public class EndDateBeforeBeginDateException : Exception { }
class example
{
void SomethingWithTime(DateTime begin, DateTime end)
{
if (begin > end) throw new EndDateBeforeBeginDateException();
// ... do something with time ....
}
void DemonstrateFunctionTriesToCorrectInsteadOfFail()
{
DateTime input_begin = new DateTime();
DateTime input_end = input_begin.AddDays(-1); // WRONG DATE ON PURPOSE!
do
{
try
{
SomethingWithTime(input_begin, input_end);
}
catch (EndDateBeforeBeginDateException)
{
// Date was most likely wrong ask user
var r = MessageBox.Show("The end date was before the begin date."
+ "Do you want to switch them and try again?",
"Switch dates?",
MessageBoxButtons.YesNo);
if (r != DialogResult.No) { return; } // quit function
var temp = input_begin;
input_begin = input_end;
input_end = temp;
continue; // Try again now
}
} while (false);
}
}
But what if you have a lot of parameters. You don't want to create thousands of exceptions. Well, you can try using tagged exceptions which looks like this.
public class TaggedException<T> : Exception { }
struct _EndDateBeforeBeginDateTag{}
struct _SameDateTag {}
struct _TimeDoesNotExistTag {}
struct _ThinkOfATagOnYourOwn {}
class example
{
void SomethingWithTime(DateTime begin, DateTime end)
{
if (begin > end) throw new TaggedException<_EndDateBeforeBeginDateTag>();
if (begin == end) throw new TaggedException<_SameDateTag>();
// ... do something with time ....
}
void DemonstrateFunctionTriesToCorrectInsteadOfFail()
{
DateTime input_begin = new DateTime();
DateTime input_end = input_begin.AddDays(-1); // WRONG DATE ON PURPOSE!
do
{
try
{
SomethingWithTime(input_begin, input_end);
}
catch (TaggedException<_EndDateBeforeBeginDateTag>)
{
// Date was most likely wrong ask user
var r = MessageBox.Show("The end date was before the begin date."
+ "Do you want to switch them and try again?",
"Switch dates?",
MessageBoxButtons.YesNo);
if (r != DialogResult.No) { return; } // quit function
var temp = input_begin;
input_begin = input_end;
input_end = temp;
continue; // Try again now
}catch (TaggedException<_SameDateTag>)
{
// Force the user to change one date
}catch (TaggedException<_ThinkOfATagOnYourOwn>)
{
// Tag seems obvious enough *wink*
}
} while (false);
}
}
Now you only have one Exception in your code though you can quickly and without having to write much code.
(And if you are smart you store extra info the tag which is stored in the exception).
The same trick also works in C++ using templates.