Code does not catch FormatException in C# - c#

I have the following method in the class ProductServices:
public bool IsDownloadAllowed(int Id, string productId)
{
if (CustomStringFunctions.IsGuid(productId))
{
//Do Something
}
else
{
throw new FormatException("The Guid must be a valid Guid!");
}
}
If I use the method in the following set of instructions:
var _productServices = new ProductServices();
try
{
var flag = _productServices.IsDownloadAllowed(Id, productId);
//do something
}
catch (Exception e)
{
//handle exception
}
The exception is not caught by the catch statement. I also tried to replace Exception with FormatException with no luck. What am I doing wrong?

You must have mute exception in this code
if (CustomStringFunctions.IsGuid(productId))
{
//Do Something
}
You must be sure that you throw exception when occured (In the Do Something)
Sample of mute exception
Try
{
}
Catch(Exception ex)
{
//throw don't exist
}

Your code looks correct. A possible explanation for your problem is that CustomStringFunctions.IsGuid is incorrectly returning true, so the \\do something branch is executing instead of the exception-throwing branch.

Related

Forward catch from method

I'm trying to grab a ComponentId of a network device, it all works but now I am trying to grab a catch from the GetKey() method. I'm just not quite sure how to forward it (or if this is even the correct way). Should I even be using try/catch in methods?
static string GetKey()
{
try
{
using (RegistryKey Adapter = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}", true))
{
foreach (string Keyname in Adapter.GetSubKeyNames())
{
RegistryKey Key = Adapter.OpenSubKey(Keyname);
if (Key.GetValue("DriverDesc").ToString() != "somename")
{
return Key.GetValue("ComponentId").ToString();
}
return null;
}
return null;
}
}
catch (Exception ex)
{
return ex.Message;
}
}
static void Main(string[] args)
{
if (GetKey() == null)
{
Console.WriteLine("null");
}
else if () // if catch throws exception?
{}
else
{
Console.WriteLine(GetKey());
}
Console.ReadKey();
}
This looks like a very bad idea to me to return the exception message in a method that returns a string (which is some key).
You need to understand: what is the reason for the try/catch? What are you trying to achieve there? If you just want to log the exception, it's better to do that in some top-level framework error handling than here.
If you want to hide some exceptions (which is generally a bad idea, but there are exceptions), then you can just return null there to indicate nothing has been found. Moreover it's quite unlikely that the exception happens after you have the value of the key you can return (or even impossible since you just return it).
It is also not 100% clear what exactly you want to forward. If it's the exception itself, then you can do this:
try
{
}
catch (Exception exception)
{
throw;
}
Now this will properly rethrow the exception with original stack trace. While this code is useless on it's own, you can add some handling before throw if you need.
Try, thats what the try, catch, finally is for
Try
{
String result = GetKey();
if (result == null)
{
Console.WriteLine("null");
}
else
{
Console.WriteLine(result);
}
}
catch
{
Console.WriteLine("Reading key failed");
}
Console.ReadKey();
Note also I changed your code from repeatedly calling GetKey - which was unnecessary
Returning an exception message when the code clearly expects some key value is a very bad idea.
The typical way to do it is to rethrow the exception as your application-specific type, with the original exception as inner. So in your catch block in the method you do:
catch (Exception ex)
{
throw new MyApplicationException(ex);
}
Where MyApplicationException is your own exception type that you then handle in your main program using
catch (MyApplicationException ex)
{
////Handle it!
}
You could write your GetKey in a bit more usable fashion with making it a TryGetKey instead just GetKey and handle exceptions. Like so
static bool TryGetKey(out string result)
{
result = null;
try
{
using (RegistryKey Adapter = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}", true))
{
foreach (string Keyname in Adapter.GetSubKeyNames())
{
RegistryKey Key = Adapter.OpenSubKey(Keyname);
if (Key.GetValue("DriverDesc").ToString() != "somename")
{
result = Key.GetValue("ComponentId").ToString();
return true;
}
}
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
return false;
}
And in your calling code you should be checking what the result of that function was in order to do something with the key or handle the failure.
var key = string.Empty;
if (TryGetKey(out key))
{
// Got key can do something.
}
else
{
// Something went wrong, what should the application do?
}
Also generally wrapping the entire code block within try-catch is considered bad practice.

How to notify an exception in C#?

I have an exception occurred when the Database connection failed in a Class. The problem is how do I notify my Main Window that this exception is caught and show a message box to notify my user?
Thanks
Use the Try ... Catch clause like this:
try
{
// The code that could generate an exception
}
catch(Exception ex)
{
MessageBox.Show("Error: " ex.Message);
}
Or if you're using SQL-Server connection, use it like this:
try
{
// The code that could generate an exception
}
catch(SqlException ex)
{
MessageBox.Show("SQL Error: " ex.Message);
}
Thanks. I may have not make my question clearly. I mean this exception
is occurred in one class, but the message box should be show in an
other windows class. So how do I communicate and show this error?
From your clarification in one of the comments:
So if you have class TestClass.cs with method Test in it.
public void Test()
{
//if you want to throw an exception defined by your business logic
if(someCondition == false)
throw CustomException();
//if you have exception in the code
int a = 5;
int b =0;
//here you will be thrown an exception can't divide by 0.
int c = a/b;
}
Your winform Button Click or whatever
public void Button_Click1(object sender, EventArgs e)
{
try
{
TestClass cl = new TestClass();
cl.Test();
}
catch(CustomException custEx)
{
//this for your Bussines logic exception
//write your message
}
catch(DivideByZeroException div)
{
//this for divide by zero exception
//write message
}
//you can catch all other exception like this but I don't advice you to do that
catch(Exception ex)
{
//for this to working properly, this catch should be under all of others(last priority)
}
}

Catch block without arg

I have a catch block like below:
catch (Exception e)
{
connection.Close();
return null;
}
I get a warning saying 'e' is not being used. I don't want to use it. But if I remove it I get an error saying "class type expected". What's to be done?
catch
{
connection.Close();
return null;
}
do this:
try
{
//code to throw exception
}
catch(ArgumentNullException)
{
//do something in response to this exception
}
catch(Exception)
{
//catch the general exception
}
this allows you to catch different types of exception without having to castch everything as with Danny's answer above (sorry i coulnd't just comment, not enough rating yet!)
Take the e out

Exception from within a finally block

Consider the following code where LockDevice() could possibly fail and throw an exception on ist own. What happens in C# if an exception is raised from within a finally block?
UnlockDevice();
try
{
DoSomethingWithDevice();
}
finally
{
LockDevice(); // can fail with an exception
}
Exactly the same thing that would happen if it wasn't in a finally block - an exception could propagate from that point. If you need to, you can try/catch from within the finally:
try
{
DoSomethingWithDevice();
}
finally
{
try
{
LockDevice();
}
catch (...)
{
...
}
}
The method is called Try / Catch
Where is your catch?
UnlockDevice();
try
{
DoSomethingWithDevice();
}
catch(Exception ex)
{
// Do something with the error on DoSomethingWithDevice()
}
finally
{
try
{
LockDevice(); // can fail with an exception
}
catch (Exception ex)
{
// Do something with the error on LockDevice()
}
}

Catch multiple exceptions at once?

It is discouraged to simply catch System.Exception. Instead, only the "known" exceptions should be caught.
Now, this sometimes leads to unnecessary repetitive code, for example:
try
{
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
WebId = Guid.Empty;
}
catch (OverflowException)
{
WebId = Guid.Empty;
}
I wonder: Is there a way to catch both exceptions and only call the WebId = Guid.Empty call once?
The given example is rather simple, as it's only a GUID. But imagine code where you modify an object multiple times, and if one of the manipulations fails expectedly, you want to "reset" the object. However, if there is an unexpected exception, I still want to throw that higher.
Catch System.Exception and switch on the types
catch (Exception ex)
{
if (ex is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
return;
}
throw;
}
EDIT: I do concur with others who are saying that, as of C# 6.0, exception filters are now a perfectly fine way to go: catch (Exception ex) when (ex is ... || ex is ... )
Except that I still kind of hate the one-long-line layout and would personally lay the code out like the following. I think this is as functional as it is aesthetic, since I believe it improves comprehension. Some may disagree:
catch (Exception ex) when (
ex is ...
|| ex is ...
|| ex is ...
)
ORIGINAL:
I know I'm a little late to the party here, but holy smoke...
Cutting straight to the chase, this kind of duplicates an earlier answer, but if you really want to perform a common action for several exception types and keep the whole thing neat and tidy within the scope of the one method, why not just use a lambda/closure/inline function to do something like the following? I mean, chances are pretty good that you'll end up realizing that you just want to make that closure a separate method that you can utilize all over the place. But then it will be super easy to do that without actually changing the rest of the code structurally. Right?
private void TestMethod ()
{
Action<Exception> errorHandler = ( ex ) => {
// write to a log, whatever...
};
try
{
// try some stuff
}
catch ( FormatException ex ) { errorHandler ( ex ); }
catch ( OverflowException ex ) { errorHandler ( ex ); }
catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}
I can't help but wonder (warning: a little irony/sarcasm ahead) why on earth go to all this effort to basically just replace the following:
try
{
// try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}
...with some crazy variation of this next code smell, I mean example, only to pretend that you're saving a few keystrokes.
// sorta sucks, let's be honest...
try
{
// try some stuff
}
catch( Exception ex )
{
if (ex is FormatException ||
ex is OverflowException ||
ex is ArgumentNullException)
{
// write to a log, whatever...
return;
}
throw;
}
Because it certainly isn't automatically more readable.
Granted, I left the three identical instances of /* write to a log, whatever... */ return; out of the first example.
But that's sort of my point. Y'all have heard of functions/methods, right? Seriously. Write a common ErrorHandler function and, like, call it from each catch block.
If you ask me, the second example (with the if and is keywords) is both significantly less readable, and simultaneously significantly more error-prone during the maintenance phase of your project.
The maintenance phase, for anyone who might be relatively new to programming, is going to compose 98.7% or more of the overall lifetime of your project, and the poor schmuck doing the maintenance is almost certainly going to be someone other than you. And there is a very good chance they will spend 50% of their time on the job cursing your name.
And of course FxCop barks at you and so you have to also add an attribute to your code that has precisely zip to do with the running program, and is only there to tell FxCop to ignore an issue that in 99.9% of cases it is totally correct in flagging. And, sorry, I might be mistaken, but doesn't that "ignore" attribute end up actually compiled into your app?
Would putting the entire if test on one line make it more readable? I don't think so. I mean, I did have another programmer vehemently argue once long ago that putting more code on one line would make it "run faster." But of course he was stark raving nuts. Trying to explain to him (with a straight face--which was challenging) how the interpreter or compiler would break that long line apart into discrete one-instruction-per-line statements--essentially identical to the result if he had gone ahead and just made the code readable instead of trying to out-clever the compiler--had no effect on him whatsoever. But I digress.
How much less readable does this get when you add three more exception types, a month or two from now? (Answer: it gets a lot less readable).
One of the major points, really, is that most of the point of formatting the textual source code that we're all looking at every day is to make it really, really obvious to other human beings what is actually happening when the code runs. Because the compiler turns the source code into something totally different and couldn't care less about your code formatting style. So all-on-one-line totally sucks, too.
Just saying...
// super sucks...
catch( Exception ex )
{
if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
{
// write to a log, whatever...
return;
}
throw;
}
As others have pointed out, you can have an if statement inside your catch block to determine what is going on. C#6 supports Exception Filters, so the following will work:
try { … }
catch (Exception e) when (MyFilter(e))
{
…
}
The MyFilter method could then look something like this:
private bool MyFilter(Exception e)
{
return e is ArgumentNullException || e is FormatException;
}
Alternatively, this can be all done inline (the right hand side of the when statement just has to be a boolean expression).
try { … }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
…
}
This is different from using an if statement from within the catch block, using exception filters will not unwind the stack.
You can download Visual Studio 2015 to check this out.
If you want to continue using Visual Studio 2013, you can install the following nuget package:
Install-Package Microsoft.Net.Compilers
At time of writing, this will include support for C# 6.
Referencing this package will cause the project to be built using the
specific version of the C# and Visual Basic compilers contained in the
package, as opposed to any system installed version.
Not in C# unfortunately, as you'd need an exception filter to do it and C# doesn't expose that feature of MSIL. VB.NET does have this capability though, e.g.
Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException
What you could do is use an anonymous function to encapsulate your on-error code, and then call it in those specific catch blocks:
Action onError = () => WebId = Guid.Empty;
try
{
// something
}
catch (FormatException)
{
onError();
}
catch (OverflowException)
{
onError();
}
Exception filters are now available in c# 6+. You can do
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception ex) when(ex is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
}
In C# 7.0+, you can combine this with pattern matching too
try
{
await Task.WaitAll(tasks);
}
catch (Exception ex) when( ex is AggregateException ae &&
ae.InnerExceptions.Count > tasks.Count/2)
{
//More than half of the tasks failed maybe..?
}
For the sake of completeness, since .NET 4.0 the code can rewritten as:
Guid.TryParse(queryString["web"], out WebId);
TryParse never throws exceptions and returns false if format is wrong, setting WebId to Guid.Empty.
Since C# 7 you can avoid introducing a variable on a separate line:
Guid.TryParse(queryString["web"], out Guid webId);
You can also create methods for parsing returning tuples, which aren't available in .NET Framework yet as of version 4.6:
(bool success, Guid result) TryParseGuid(string input) =>
(Guid.TryParse(input, out Guid result), result);
And use them like this:
WebId = TryParseGuid(queryString["web"]).result;
// or
var tuple = TryParseGuid(queryString["web"]);
WebId = tuple.success ? tuple.result : DefaultWebId;
Next useless update to this useless answer comes when deconstruction of out-parameters is implemented in C# 12. :)
If you can upgrade your application to C# 6 you are lucky. The new C# version has implemented Exception filters. So you can write this:
catch (Exception ex) when (ex is FormatException || ex is OverflowException) {
WebId = Guid.Empty;
}
Some people think this code is the same as
catch (Exception ex) {
if (ex is FormatException || ex is OverflowException) {
WebId = Guid.Empty;
}
throw;
}
But it´s not. Actually this is the only new feature in C# 6 that is not possible to emulate in prior versions. First, a re-throw means more overhead than skipping the catch. Second, it is not semantically equivalent. The new feature preserves the stack intact when you are debugging your code. Without this feature the crash dump is less useful or even useless.
See a discussion about this on CodePlexNot available anymore. And an example showing the difference.
Update for C# 9
Using the new pattern matching enhancements made in C# 9, you can shorten the expression in the exception filter. Now, catching multiple exceptions is a simple is this:
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception e) when (e is FormatException or OverflowException)
{
WebId = Guid.Empty;
}
With C# 7 the answer from Michael Stum can be improved while keeping the readability of a switch statement:
catch (Exception ex)
{
switch (ex)
{
case FormatException _:
case OverflowException _:
WebId = Guid.Empty;
break;
default:
throw;
}
}
Thanks to Orace comment this can be simplified with C# 8 by omitting the discard variable:
catch (Exception ex)
{
switch (ex)
{
case FormatException:
case OverflowException:
WebId = Guid.Empty;
break;
default:
throw;
}
}
And with C# 8 as switch expression:
catch (Exception ex)
{
WebId = ex switch
{
_ when ex is FormatException || ex is OverflowException => Guid.Empty,
_ => throw ex
};
}
As Nechemia Hoffmann pointed out. The latter example will cause a loss of the stacktrace. This can be prevented by using the extension method described by Jürgen Steinblock to capture the stacktrace before throwing:
catch (Exception ex)
{
WebId = ex switch
{
_ when ex is FormatException || ex is OverflowException => Guid.Empty,
_ => throw ex.Capture()
};
}
public static Exception Capture(this Exception ex)
{
ExceptionDispatchInfo.Capture(ex).Throw();
return ex;
}
Both styles can be simplified with the pattern matching enhancements of C# 9:
catch (Exception ex)
{
switch (ex)
{
case FormatException or OverflowException:
WebId = Guid.Empty;
break;
default:
throw;
}
}
catch (Exception ex)
{
WebId = ex switch
{
_ when ex is FormatException or OverflowException => Guid.Empty,
_ => throw ex.Capture()
};
}
If you don't want to use an if statement within the catch scopes, in C# 6.0 you can use Exception Filters syntax which was already supported by the CLR in previews versions but existed only in VB.NET/MSIL:
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception exception) when (exception is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
}
This code will catch the Exception only when it's a InvalidDataException or ArgumentNullException.
Actually, you can put basically any condition inside that when clause:
static int a = 8;
...
catch (Exception exception) when (exception is InvalidDataException && a == 8)
{
Console.WriteLine("Catch");
}
Note that as opposed to an if statement inside the catch's scope, Exception Filters cannot throw Exceptions, and when they do, or when the condition is not true, the next catch condition will be evaluated instead:
static int a = 7;
static int b = 0;
...
try
{
throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
Console.WriteLine("General catch");
}
Output: General catch.
When there is more then one true Exception Filter - the first one will be accepted:
static int a = 8;
static int b = 4;
...
try
{
throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
Console.WriteLine("General catch");
}
Output: Catch.
And as you can see in the MSIL the code is not translated to if statements, but to Filters, and Exceptions cannot be throw from within the areas marked with Filter 1 and Filter 2 but the filter throwing the Exception will fail instead, also the last comparison value pushed to the stack before the endfilter command will determine the success/failure of the filter (Catch 1 XOR Catch 2 will execute accordingly):
Also, specifically Guid has the Guid.TryParse method.
catch (Exception ex) when (ex is FormatException or OverflowException)
{
WebId = Guid.Empty;
}
or
catch (Exception ex)
{
if (ex is not FormatException and not OverflowException)
throw;
WebId = Guid.Empty;
}
The accepted answer seems acceptable, except that CodeAnalysis/FxCop will complain about the fact that it's catching a general exception type.
Also, it seems the "is" operator might degrade performance slightly.
CA1800: Do not cast unnecessarily says to "consider testing the result of the 'as' operator instead", but if you do that, you'll be writing more code than if you catch each exception separately.
Anyhow, here's what I would do:
bool exThrown = false;
try
{
// Something
}
catch (FormatException) {
exThrown = true;
}
catch (OverflowException) {
exThrown = true;
}
if (exThrown)
{
// Something else
}
in C# 6 the recommended approach is to use Exception Filters, here is an example:
try
{
throw new OverflowException();
}
catch(Exception e ) when ((e is DivideByZeroException) || (e is OverflowException))
{
// this will execute iff e is DividedByZeroEx or OverflowEx
Console.WriteLine("E");
}
This is a variant of Matt's answer (I feel that this is a bit cleaner)...use a method:
public void TryCatch(...)
{
try
{
// something
return;
}
catch (FormatException) {}
catch (OverflowException) {}
WebId = Guid.Empty;
}
Any other exceptions will be thrown and the code WebId = Guid.Empty; won't be hit. If you don't want other exceptions to crash your program, just add this AFTER the other two catches:
...
catch (Exception)
{
// something, if anything
return; // only need this if you follow the example I gave and put it all in a method
}
Joseph Daigle's Answer is a good solution, but I found the following structure to be a bit tidier and less error prone.
catch(Exception ex)
{
if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
There are a few advantages of inverting the expression:
A return statement is not necessary
The code isn't nested
There's no risk of forgetting the 'throw' or 'return' statements that in Joseph's solution are separated from the expression.
It can even be compacted to a single line (though not very pretty)
catch(Exception ex) { if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
Edit:
The exception filtering in C# 6.0 will make the syntax a bit cleaner and comes with a number of other benefits over any current solution. (most notably leaving the stack unharmed)
Here is how the same problem would look using C# 6.0 syntax:
catch(Exception ex) when (ex is SomeException || ex is OtherException)
{
// Handle exception
}
#Micheal
Slightly revised version of your code:
catch (Exception ex)
{
Type exType = ex.GetType();
if (exType == typeof(System.FormatException) ||
exType == typeof(System.OverflowException)
{
WebId = Guid.Empty;
} else {
throw;
}
}
String comparisons are ugly and slow.
How about
try
{
WebId = Guid.Empty;
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
}
catch (OverflowException)
{
}
Cautioned and Warned: Yet another kind, functional style.
What is in the link doesn't answer your question directly, but it's trivial to extend it to look like:
static void Main()
{
Action body = () => { ...your code... };
body.Catch<InvalidOperationException>()
.Catch<BadCodeException>()
.Catch<AnotherException>(ex => { ...handler... })();
}
(Basically provide another empty Catch overload which returns itself)
The bigger question to this is why. I do not think the cost outweighs the gain here :)
Update 2015-12-15: See https://stackoverflow.com/a/22864936/1718702 for C#6. It's a cleaner and now standard in the language.
Geared for people that want a more elegant solution to catch once and filter exceptions, I use an extension method as demonstrated below.
I already had this extension in my library, originally written for other purposes, but it worked just perfectly for type checking on exceptions. Plus, imho, it looks cleaner than a bunch of || statements. Also, unlike the accepted answer, I prefer explicit exception handling so ex is ... had undesireable behaviour as derrived classes are assignable to there parent types).
Usage
if (ex.GetType().IsAnyOf(
typeof(FormatException),
typeof(ArgumentException)))
{
// Handle
}
else
throw;
IsAnyOf.cs Extension (See Full Error Handling Example for Dependancies)
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter matches at least one of the passed in comparisons.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_comparisons">Values to compare against.</param>
/// <returns>True if a match is found.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
{
// Validate
p_parameter
.CannotBeNull("p_parameter");
p_comparisons
.CannotBeNullOrEmpty("p_comparisons");
// Test for any match
foreach (var item in p_comparisons)
if (p_parameter.Equals(item))
return true;
// Return no matches found
return false;
}
}
}
Full Error Handling Example (Copy-Paste to new Console app)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.FluentValidation;
namespace IsAnyOfExceptionHandlerSample
{
class Program
{
static void Main(string[] args)
{
// High Level Error Handler (Log and Crash App)
try
{
Foo();
}
catch (OutOfMemoryException ex)
{
Console.WriteLine("FATAL ERROR! System Crashing. " + ex.Message);
Console.ReadKey();
}
}
static void Foo()
{
// Init
List<Action<string>> TestActions = new List<Action<string>>()
{
(key) => { throw new FormatException(); },
(key) => { throw new ArgumentException(); },
(key) => { throw new KeyNotFoundException();},
(key) => { throw new OutOfMemoryException(); },
};
// Run
foreach (var FooAction in TestActions)
{
// Mid-Level Error Handler (Appends Data for Log)
try
{
// Init
var SomeKeyPassedToFoo = "FooParam";
// Low-Level Handler (Handle/Log and Keep going)
try
{
FooAction(SomeKeyPassedToFoo);
}
catch (Exception ex)
{
if (ex.GetType().IsAnyOf(
typeof(FormatException),
typeof(ArgumentException)))
{
// Handle
Console.WriteLine("ex was {0}", ex.GetType().Name);
Console.ReadKey();
}
else
{
// Add some Debug info
ex.Data.Add("SomeKeyPassedToFoo", SomeKeyPassedToFoo.ToString());
throw;
}
}
}
catch (KeyNotFoundException ex)
{
// Handle differently
Console.WriteLine(ex.Message);
int Count = 0;
if (!Validate.IsAnyNull(ex, ex.Data, ex.Data.Keys))
foreach (var Key in ex.Data.Keys)
Console.WriteLine(
"[{0}][\"{1}\" = {2}]",
Count, Key, ex.Data[Key]);
Console.ReadKey();
}
}
}
}
}
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter matches at least one of the passed in comparisons.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_comparisons">Values to compare against.</param>
/// <returns>True if a match is found.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
{
// Validate
p_parameter
.CannotBeNull("p_parameter");
p_comparisons
.CannotBeNullOrEmpty("p_comparisons");
// Test for any match
foreach (var item in p_comparisons)
if (p_parameter.Equals(item))
return true;
// Return no matches found
return false;
}
/// <summary>
/// Validates if any passed in parameter is equal to null.
/// </summary>
/// <param name="p_parameters">Parameters to test for Null.</param>
/// <returns>True if one or more parameters are null.</returns>
public static bool IsAnyNull(params object[] p_parameters)
{
p_parameters
.CannotBeNullOrEmpty("p_parameters");
foreach (var item in p_parameters)
if (item == null)
return true;
return false;
}
}
}
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter is not null, throwing a detailed exception message if the test fails.
/// </summary>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_name">Name of tested parameter to assist with debugging.</param>
/// <exception cref="ArgumentNullException"></exception>
public static void CannotBeNull(this object p_parameter, string p_name)
{
if (p_parameter == null)
throw
new
ArgumentNullException(
string.Format("Parameter \"{0}\" cannot be null.",
p_name), default(Exception));
}
}
}
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter is not null or an empty collection, throwing a detailed exception message if the test fails.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_name">Name of tested parameter to assist with debugging.</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static void CannotBeNullOrEmpty<T>(this ICollection<T> p_parameter, string p_name)
{
if (p_parameter == null)
throw new ArgumentNullException("Collection cannot be null.\r\nParameter_Name: " + p_name, default(Exception));
if (p_parameter.Count <= 0)
throw new ArgumentOutOfRangeException("Collection cannot be empty.\r\nParameter_Name: " + p_name, default(Exception));
}
/// <summary>
/// Validates the passed in parameter is not null or empty, throwing a detailed exception message if the test fails.
/// </summary>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_name">Name of tested parameter to assist with debugging.</param>
/// <exception cref="ArgumentException"></exception>
public static void CannotBeNullOrEmpty(this string p_parameter, string p_name)
{
if (string.IsNullOrEmpty(p_parameter))
throw new ArgumentException("String cannot be null or empty.\r\nParameter_Name: " + p_name, default(Exception));
}
}
}
Two Sample NUnit Unit Tests
Matching behaviour for Exception types is exact (ie. A child IS NOT a match for any of its parent types).
using System;
using System.Collections.Generic;
using Common.FluentValidation;
using NUnit.Framework;
namespace UnitTests.Common.Fluent_Validations
{
[TestFixture]
public class IsAnyOf_Tests
{
[Test, ExpectedException(typeof(ArgumentNullException))]
public void IsAnyOf_ArgumentNullException_ShouldNotMatch_ArgumentException_Test()
{
Action TestMethod = () => { throw new ArgumentNullException(); };
try
{
TestMethod();
}
catch (Exception ex)
{
if (ex.GetType().IsAnyOf(
typeof(ArgumentException), /*Note: ArgumentNullException derrived from ArgumentException*/
typeof(FormatException),
typeof(KeyNotFoundException)))
{
// Handle expected Exceptions
return;
}
//else throw original
throw;
}
}
[Test, ExpectedException(typeof(OutOfMemoryException))]
public void IsAnyOf_OutOfMemoryException_ShouldMatch_OutOfMemoryException_Test()
{
Action TestMethod = () => { throw new OutOfMemoryException(); };
try
{
TestMethod();
}
catch (Exception ex)
{
if (ex.GetType().IsAnyOf(
typeof(OutOfMemoryException),
typeof(StackOverflowException)))
throw;
/*else... Handle other exception types, typically by logging to file*/
}
}
}
}
Note that I did find one way to do it, but this looks more like material for The Daily WTF:
catch (Exception ex)
{
switch (ex.GetType().Name)
{
case "System.FormatException":
case "System.OverflowException":
WebId = Guid.Empty;
break;
default:
throw;
}
}
Since I felt like these answers just touched the surface, I attempted to dig a bit deeper.
So what we would really want to do is something that doesn't compile, say:
// Won't compile... damn
public static void Main()
{
try
{
throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException)
catch (IndexOutOfRangeException)
{
// ... handle
}
The reason we want this is because we don't want the exception handler to catch things that we need later on in the process. Sure, we can catch an Exception and check with an 'if' what to do, but let's be honest, we don't really want that. (FxCop, debugger issues, uglyness)
So why won't this code compile - and how can we hack it in such a way that it will?
If we look at the code, what we really would like to do is forward the call. However, according to the MS Partition II, IL exception handler blocks won't work like this, which in this case makes sense because that would imply that the 'exception' object can have different types.
Or to write it in code, we ask the compiler to do something like this (well it's not entirely correct, but it's the closest possible thing I guess):
// Won't compile... damn
try
{
throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException e) {
goto theOtherHandler;
}
catch (IndexOutOfRangeException e) {
theOtherHandler:
Console.WriteLine("Handle!");
}
The reason that this won't compile is quite obvious: what type and value would the '$exception' object have (which are here stored in the variables 'e')? The way we want the compiler to handle this is to note that the common base type of both exceptions is 'Exception', use that for a variable to contain both exceptions, and then handle only the two exceptions that are caught. The way this is implemented in IL is as 'filter', which is available in VB.Net.
To make it work in C#, we need a temporary variable with the correct 'Exception' base type. To control the flow of the code, we can add some branches. Here goes:
Exception ex;
try
{
throw new ArgumentException(); // for demo purposes; won't be caught.
goto noCatch;
}
catch (ArgumentOutOfRangeException e) {
ex = e;
}
catch (IndexOutOfRangeException e) {
ex = e;
}
Console.WriteLine("Handle the exception 'ex' here :-)");
// throw ex ?
noCatch:
Console.WriteLine("We're done with the exception handling.");
The obvious disadvantages for this are that we cannot re-throw properly, and -well let's be honest- that it's quite the ugly solution. The uglyness can be fixed a bit by performing branch elimination, which makes the solution slightly better:
Exception ex = null;
try
{
throw new ArgumentException();
}
catch (ArgumentOutOfRangeException e)
{
ex = e;
}
catch (IndexOutOfRangeException e)
{
ex = e;
}
if (ex != null)
{
Console.WriteLine("Handle the exception here :-)");
}
That leaves just the 're-throw'. For this to work, we need to be able to perform the handling inside the 'catch' block - and the only way to make this work is by an catching 'Exception' object.
At this point, we can add a separate function that handles the different types of Exceptions using overload resolution, or to handle the Exception. Both have disadvantages. To start, here's the way to do it with a helper function:
private static bool Handle(Exception e)
{
Console.WriteLine("Handle the exception here :-)");
return true; // false will re-throw;
}
public static void Main()
{
try
{
throw new OutOfMemoryException();
}
catch (ArgumentException e)
{
if (!Handle(e)) { throw; }
}
catch (IndexOutOfRangeException e)
{
if (!Handle(e)) { throw; }
}
Console.WriteLine("We're done with the exception handling.");
And the other solution is to catch the Exception object and handle it accordingly. The most literal translation for this, based on the context above is this:
try
{
throw new ArgumentException();
}
catch (Exception e)
{
Exception ex = (Exception)(e as ArgumentException) ?? (e as IndexOutOfRangeException);
if (ex != null)
{
Console.WriteLine("Handle the exception here :-)");
// throw ?
}
else
{
throw;
}
}
So to conclude:
If we don't want to re-throw, we might consider catching the right exceptions, and storing them in a temporary.
If the handler is simple, and we want to re-use code, the best solution is probably to introduce a helper function.
If we want to re-throw, we have no choice but to put the code in a 'Exception' catch handler, which will break FxCop and your debugger's uncaught exceptions.
This is a classic problem every C# developer faces eventually.
Let me break your question into 2 questions. The first,
Can I catch multiple exceptions at once?
In short, no.
Which leads to the next question,
How do I avoid writing duplicate code given that I can't catch multiple exception types in the same catch() block?
Given your specific sample, where the fall-back value is cheap to construct, I like to follow these steps:
Initialize WebId to the fall-back value.
Construct a new Guid in a temporary variable.
Set WebId to the fully constructed temporary variable. Make this the final statement of the try{} block.
So the code looks like:
try
{
WebId = Guid.Empty;
Guid newGuid = new Guid(queryString["web"]);
// More initialization code goes here like
// newGuid.x = y;
WebId = newGuid;
}
catch (FormatException) {}
catch (OverflowException) {}
If any exception is thrown, then WebId is never set to the half-constructed value, and remains Guid.Empty.
If constructing the fall-back value is expensive, and resetting a value is much cheaper, then I would move the reset code into its own function:
try
{
WebId = new Guid(queryString["web"]);
// More initialization code goes here.
}
catch (FormatException) {
Reset(WebId);
}
catch (OverflowException) {
Reset(WebId);
}
So you´re repeating lots of code within every exception-switch? Sounds like extracting a method would be god idea, doesn´t it?
So your code comes down to this:
MyClass instance;
try { instance = ... }
catch(Exception1 e) { Reset(instance); }
catch(Exception2 e) { Reset(instance); }
catch(Exception) { throw; }
void Reset(MyClass instance) { /* reset the state of the instance */ }
I wonder why no-one noticed that code-duplication.
From C#6 you furthermore have the exception-filters as already mentioned by others. So you can modify the code above to this:
try { ... }
catch(Exception e) when(e is Exception1 || e is Exception2)
{
Reset(instance);
}
Wanted to added my short answer to this already long thread. Something that hasn't been mentioned is the order of precedence of the catch statements, more specifically you need to be aware of the scope of each type of exception you are trying to catch.
For example if you use a "catch-all" exception as Exception it will preceed all other catch statements and you will obviously get compiler errors however if you reverse the order you can chain up your catch statements (bit of an anti-pattern I think) you can put the catch-all Exception type at the bottom and this will be capture any exceptions that didn't cater for higher up in your try..catch block:
try
{
// do some work here
}
catch (WebException ex)
{
// catch a web excpetion
}
catch (ArgumentException ex)
{
// do some stuff
}
catch (Exception ex)
{
// you should really surface your errors but this is for example only
throw new Exception("An error occurred: " + ex.Message);
}
I highly recommend folks review this MSDN document:
Exception Hierarchy
Maybe try to keep your code simple such as putting the common code in a method, as you would do in any other part of the code that is not inside a catch clause?
E.g.:
try
{
// ...
}
catch (FormatException)
{
DoSomething();
}
catch (OverflowException)
{
DoSomething();
}
// ...
private void DoSomething()
{
// ...
}
Just how I would do it, trying to find the simple is beautiful pattern
It is worth mentioning here. You can respond to the multiple combinations (Exception error and exception.message).
I ran into a use case scenario when trying to cast control object in a datagrid, with either content as TextBox, TextBlock or CheckBox. In this case the returned Exception was the same, but the message varied.
try
{
//do something
}
catch (Exception ex) when (ex.Message.Equals("the_error_message1_here"))
{
//do whatever you like
}
catch (Exception ex) when (ex.Message.Equals("the_error_message2_here"))
{
//do whatever you like
}
I want to suggest shortest answer (one more functional style):
Catch<FormatException, OverflowException>(() =>
{
WebId = new Guid(queryString["web"]);
},
exception =>
{
WebId = Guid.Empty;
});
For this you need to create several "Catch" method overloads, similar to System.Action:
[DebuggerNonUserCode]
public static void Catch<TException1, TException2>(Action tryBlock,
Action<Exception> catchBlock)
{
CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2));
}
[DebuggerNonUserCode]
public static void Catch<TException1, TException2, TException3>(Action tryBlock,
Action<Exception> catchBlock)
{
CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2), typeof(TException3));
}
and so on as many as you wish. But you need to do it once and you can use it in all your projects (or, if you created a nuget package we could use it too).
And CatchMany implementation:
[DebuggerNonUserCode]
public static void CatchMany(Action tryBlock, Action<Exception> catchBlock,
params Type[] exceptionTypes)
{
try
{
tryBlock();
}
catch (Exception exception)
{
if (exceptionTypes.Contains(exception.GetType())) catchBlock(exception);
else throw;
}
}
p.s. I haven't put null checks for code simplicity, consider to add parameter validations.
p.s.2
If you want to return a value from the catch, it's necessary to do same Catch methods, but with returns and Func instead of Action in parameters.
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception ex)
{
string ExpTyp = ex.GetType().Name;
if (ExpTyp == "FormatException")
{
WebId = Guid.Empty;
}
else if (ExpTyp == "OverflowException")
{
WebId = Guid.Empty;
}
}
In c# 6.0,Exception Filters is improvements for exception handling
try
{
DoSomeHttpRequest();
}
catch (System.Web.HttpException e)
{
switch (e.GetHttpCode())
{
case 400:
WriteLine("Bad Request");
case 500:
WriteLine("Internal Server Error");
default:
WriteLine("Generic Error");
}
}

Categories

Resources