How to catch all types of exception in one single catch block?
Solution 1
To handle all exception, use Exception class.
try
{
}
catch(Exception ex)
{
switch (ex.GetType().ToString())
{
case "System.InvalidOperationException":
//cast ex to specific type of exception to use it's properties
((InvalidOperationException)ex).SomeMethod();
break;
case "System.NotSupportedException":
((System.NotSupportedException)ex).AnotherMethod();
break;
case "System.Web.Services.Protocols.SoapException":
((System.Web.Services.Protocols.SoapException)ex).OtherMethod();
break;
}
}
Why can't you just use multiple catch block anyway?
Solution 2
User2808350 is correct that try catch blocks can have many different catches for a reason, however sometimes you find you are repeating yourself (DRY) when using this pattern.
An alternative that can result in concise, readable code is to use the is operator which evaluates to true if your exception is an instance of a particular type or one that derives from that type. Unfortunately it's not possible to use the is operator in a switch block, so you have to use if-then-else.
Here is an example where I test the exception type and set the exit code accordingly.
try
{
// try something
}
catch (Exception e)
{
if (e is FileNotFoundException)
Environment.ExitCode = 2;
else if (e is InvalidOperationException)
Environment.ExitCode = 1;
else
Environment.ExitCode = 42;
throw;
}
Solution 3
This is now a language feature. Just use a switch/case statement
The asker's first attempt, shown commented out in the code snippet in the question, is now the easiest and in my opinion best way to do this.
I actually came across this question while trying to figure out what Resharper had done with one of its suggested improvements. I'm still not 100% sure on the terminology involved as the only documentation I could find was explaining Discards and only mentions in passing the "pattern matching with the is and switch keywords" that is also being performed.
I had started, as Onkel-j reccomends, with a chain of 'if ex is Type':
try
{
doWork();
}
catch (Exception ex)
{
if (ex is SpecificExceptionType)
{
//todo
}
else
{
//etc
}
}
but resharper suggested I let it change this to a switch/case:
try
{
doWork();
}
catch (Exception ex)
{
switch (ex)
{
case SpecificExceptionType _:
//todo
break;
default:
//etc
break;
}
}
Resharper has used Discards to do a sort of automatic is and toss out the unused variable. If you need to actually use the exception as the specific type, give it a name in place of the underscore:
try
{
doWork();
}
catch (Exception ex)
{
switch (ex)
{
case SpecificExceptionType specific:
HandleSpecificException(specific);
break;
default:
//etc
break;
}
}
Or to answer the original question:
catch(Exception ex)
{
//do what you want here
switch(ex)
{
case System.Web.Services.Protocols.SoapException soapEx:
if (soapEx.Code.Name.Equals("Client"))
{
msg = "service's function not exist";
}
else if (soapEx.Code.Name.Equals("Server"))
{
msg = "function error"
}
else
{
msg = "unknown";
}
MessageBox.Show(msg, "error", MessageBoxButtons.OK);
break;
case System.Net.WebException webEx:
switch (webEx.Status)
{
case System.Net.WebExceptionStatus.ConnectFailure:
//do some thing
break;
case System.Net.WebExceptionStatus.Timeout:
//do some thing
break;
case System.Net.WebExceptionStatus.ProtocolError:
switch (((System.Net.HttpWebResponse)webEx.Response).StatusCode)
{
case System.Net.HttpStatusCode.NotFound:
//do some thing
break;
case System.Net.HttpStatusCode.ServiceUnavailable:
//do some thing
break;
case System.Net.HttpStatusCode.Unauthorized:
//do some thing
break;
default:
//do some thing
break;
}
break;
default:
//do some thing
break;
}
break;
default:
//etc
break;
}
}
Solution 4
Should use
try {
....
}
catch (System.Net.HttpStatusCode.NotFound)
{
//do some thing
}
catch (System.Net.HttpStatusCode.ServiceUnavailable)
{
//do some thing
}
catch (System.Net.HttpStatusCode.Unauthorized)
{
//do some thing
}
catch (System.Net.HttpStatusCode.NotFound)
{
//do some thing
}
catch (Exception)
{
//do some thing
}
It's better that using swicth
user1299527
Updated on June 23, 2022Comments
-
user1299527 almost 2 years
catch(Exception ex) { //do what you want here //When type of exception is System.Web.Services.Protocols.SoapException //if (ex.Code.Name.Equals("Client")) //{ // msg = "service's function not exist"; //} //else if (ex.Code.Name.Equals("Server")) //{ // msg = "function error" //} //else //{ // msg = "unknown"; //} //MessageBox.Show(msg, "error", MessageBoxButtons.OK); **But ex is not System.Web.Services.Protocols.SoapException so I cannot call ex.Code.Name.Equals("Client")** //When System.Net.WebException //switch (ex.Status) //{ // case System.Net.WebExceptionStatus.ConnectFailure: // do some thing break; // case System.Net.WebExceptionStatus.Timeout: //do some thing break; // case System.Net.WebExceptionStatus.ProtocolError: switch (((System.Net.HttpWebResponse)ex.Response).StatusCode) { case System.Net.HttpStatusCode.NotFound: //do some thing break; case System.Net.HttpStatusCode.ServiceUnavailable: //do some thing break; case System.Net.HttpStatusCode.Unauthorized: //do some thing break; default: //do some thing break; } break; default: //do some thing break; } }
But Exception is not System.Net.WebException. So cannot call ex.Status
My problem:
I have a Smartclient software include WindowsForm as client and a webservice as server. Client and Server both are n-tiers application I have tested and found that has any problem when call service from Client
- in app.config: service's path wrrong . I catch System.NotSupportedException
- Or when the server cannot connect: System.Net.WebExceptionStatus
- Server's webconfig is wrong : System.InvalidOperationException
- Service throws an exception: System.Web.Services.Protocols.SoapException ...
My Idea
I call the Exception that as representative of all other exception types is representativeAlException I have namespace : Common and two classese representativeAlException.cs and BusinessExceptionHandler.cs
Make a common function with a param as (representativeAlException ex)
try { Err_LogCheck.Service1.Service1 service = new Err_LogCheck.Service1.Service1(); return service.getDeviceByZero(ZERO); } catch (Common.representativeAlException ex) { Common.BusinessExceptionHandler.ProcessException(ex); }
What I want to do
Where the service is called. Only one catch block can handler for all type of Exception
in ProcessException(representativeAlException ex) function
switch (ex) { case System.InvalidOperationException: //Do some thing break; case System.NotSupportedException: //Do some thing break; case System.Web.Services.Protocols.SoapException: //do some thing break; ... ...
-
kazinix over 11 yearsTry my answer, I cast ex to specific exception so you can use the methods and properties of that specific exception.
-
Enigmativity over 11 yearsSeriously, don't do a catch-all exception block. It's a bad programming practice. Only catch specific exceptions.
-
user1299527 over 11 yearsi do catch-all in any where. But the exception is separated to any type in a common function
-
user1299527 over 11 yearsex is not Exception. "I call the Exception that as representative of all other exception types is representativeAlException". My catch block is : catch (Common.representativeAlException ex)
-
kazinix over 11 yearsYour question is not clear so I assumed you want to handle all types of exception. I'm trying to help but all I get is downvote.
-
user1299527 over 11 yearsi am sorry because of my bad english. I want to do that: where the webservice is called, using only one catch block instead of many catch block for many exception types. And in my common function, i will check type of exception and send each message to end-user
-
kazinix over 11 yearsHave you tried my codes, it's meant to catch all types of exception.
-
siride over 11 yearsThis is the answer, best as I can tell, based on the question. I'm not sure why it got downvoted.
-
Kirk Woll over 11 years@dpp, your answer is OK, but it would be better to use the syntax that was designed for this. Get rid of the exception type altogether. i.e.
try {} catch {}
. C# does not require you to specify the exception you are trying to catch. -
user1299527 over 11 yearsi written alot. But cannot post my answer. So sorry
-
Kirk Woll over 11 years@user1299527, I understand that English is not your first language, but reading "i written alot. But cannot post my answer. So sorry" I do not understand what you are getting at.
-
user1299527 over 11 yearsthank you. I have edited my question's content. Hope that you can understand my question
-
kazinix over 11 yearsSoapException is derived from SystemException which is derived from Exception, is it not? Why couldn't the try-catch block catch the SoapException?
-
user1299527 over 11 yearsSoapException : SystemException, SystemException : Exception. But if catch (Exception ex) so ex has not properties of SoapException. I think catch Exception can catch any exception types but can not using Exception as SoapException when catch with Exception instead of SoapException
-
kazinix over 11 yearsNo, no, no. ex will have the properties of SoapException if the exception catched is SoapException, we are just using Exception so that we can catch different types of exception.
-
kazinix over 11 years@user1299527 Try the codes above, cast ex to specific exception so you can use the properties of that specific exception.
-
user1299527 over 11 yearsdpp , i want to vote you. But cannot. Because of not enough reputation. thank! If Using multiple catch block, i have to write many code in any where the service is called. Only one catch block. And i build a common function. To detach the type of exception. And return the best message to end-user.
-
kazinix over 11 yearsIt's okay, you're welcome. It's not about the votes anyway. :)
-
kazinix over 11 yearsJust check my post as answer when you can.
-
kazinix over 11 yearsthere's a white check on the upper left part of my post, just check it, if you can't just leave it, it's fine with me.
-
Tamas Molnar over 8 yearsUpvoting, because mentioning the DRY principle. Which is why I ended up doing it this way.
-
Felini about 6 yearsThis doesn't answer original question, neither any proof for "this way is better" was provided.
-
Felini about 6 yearsI think this could be improved with usage of nameof() - removes lack of typing when checking for matches.
-
Felini about 6 yearsReading this exact code is noticeably harder compared to switch statements, which can be inlined due to short lines. While this is not wrong, I doubt using "is" is worth the added reading complexity.