I'm trying to get better at handling exceptions but I feel like my code gets very ugly, unreadable and cluttered when I try my best to catch them. I would love to see how other people approach this by giving a practical example and compare solutions.
My example method downloads data from an URL and tries to serialize it into a given type, then return an instance populated with the data.
First, without any exception-handling at all:
private static T LoadAndSerialize<T>(string url)
{
var uri = new Uri(url);
var request = WebRequest.Create(uri);
var response = request.GetResponse();
var stream = response.GetResponseStream();
var result = Activator.CreateInstance<T>();
var serializer = new DataContractJsonSerializer(result.GetType());
return (T)serializer.ReadObject(stream);
}
I feel like the method is fairly readable like this. I know there are a few unnecessary steps in the method (like WebRequest.Create() can take a string, and I could chain methods without giving them variables) there but I will leave it like this to better compare against the version with exception-handling.
This is an first attempt to handle everything that could go wrong:
private static T LoadAndSerialize<T>(string url)
{
Uri uri;
WebRequest request;
WebResponse response;
Stream stream;
T instance;
DataContractJsonSerializer serializer;
try
{
uri = new Uri(url);
}
catch (Exception e)
{
throw new Exception("LoadAndSerialize : Parameter 'url' is malformed or missing.", e);
}
try
{
request = WebRequest.Create(uri);
}
catch (Exception e)
{
throw new Exception("LoadAndSerialize : Unable to create WebRequest.", e);
}
try
{
response = request.GetResponse();
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Error while getting response from host '{0}'.", uri.Host), e);
}
if (response == null) throw new Exception(string.Format("LoadAndSerialize : No response from host '{0}'.", uri.Host));
try
{
stream = response.GetResponseStream();
}
catch (Exception e)
{
throw new Exception("LoadAndSerialize : Unable to get stream from response.", e);
}
if (stream == null) throw new Exception("LoadAndSerialize : Unable to get a stream from response.");
try
{
instance = Activator.CreateInstance<T>();
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Unable to create and instance of '{0}' (no parameterless constructor?).", typeof(T).Name), e);
}
try
{
serializer = new DataContractJsonSerializer(instance.GetType());
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Unable to create serializer for '{0}' (databinding issues?).", typeof(T).Name), e);
}
try
{
instance = (T)serializer.ReadObject(stream);
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Unable to serialize stream into '{0}'.", typeof(T).Name), e);
}
return instance;
}
The problem here is that while everything that could possibly go wrong will be caught and given a somewhat meaningful exception, it is a clutter-fest of significant proportions.
So, what if I chain the catching instead. My next attempt is this:
private static T LoadAndSerialize<T>(string url)
{
try
{
var uri = new Uri(url);
var request = WebRequest.Create(uri);
var response = request.GetResponse();
var stream = response.GetResponseStream();
var serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(stream);
}
catch (ArgumentNullException e)
{
throw new Exception("LoadAndSerialize : Parameter 'url' cannot be null.", e);
}
catch (UriFormatException e)
{
throw new Exception("LoadAndSerialize : Parameter 'url' is malformed.", e);
}
catch (NotSupportedException e)
{
throw new Exception("LoadAndSerialize : Unable to create WebRequest or get response stream, operation not supported.", e);
}
catch (System.Security.SecurityException e)
{
throw new Exception("LoadAndSerialize : Unable to create WebRequest, operation was prohibited.", e);
}
catch (NotImplementedException e)
{
throw new Exception("LoadAndSerialize : Unable to get response from WebRequest, method not implemented?!.", e);
}
catch(NullReferenceException e)
{
throw new Exception("LoadAndSerialize : Response or stream was empty.", e);
}
}
While it certainly is easier on the eyes, I am leaning heavily the intellisense here to provide all exceptions that can possibly be thrown from a method or class. I don't feel confident that this documentation is 100% accurate, and would be even more skeptical if some of the methods came from an assembly outside the .net framework. As an example the DataContractJsonSerializer show no exceptions on the intellisense. Does this mean the constructor will never fail? Can I be sure?
Other issues with this is that some of the methods throw the same exception, which makes the error harder to describe (this or this or this went wrong) and so is less useful to the user / debugger.
A third option would be to ignore all exceptions apart from the ones that would allow me to take an action like retrying the connection. If the url is null then the url is null, the only benefit from catching that is a little bit more verbose error message.
I would love to see your thoughts and/or implementations!
Rule one of exception handling - do not catch exceptions you don't know how to handle.
Catching exceptions just in order to provide nice error messages is questionable. The exception type and message already contain enough information for a developer - the messages you have provided do not add any value.
the DataContractJsonSerializer show no exceptions on the intellisense. Does this mean the constructor will never fail? Can I be sure?
No, you can't be sure. C# and .NET in general are not like Java where you have to declare what exceptions may be thrown.
A third option would be to ignore all exceptions apart from the ones that would allow me to take an action like retrying the connection.
That indeed is the best option.
You can also add a general exception handler at the top of the application that will capture all unhandled exceptions and log them.
First, read my article on exception handling:
http://ericlippert.com/2008/09/10/vexing-exceptions/
My advice is: you must handle the "vexing exceptions" and "exogenous exceptions" that can be thrown by your code. Vexing exceptions are "non exceptional" exceptions and so you have to handle them. Exogenous exceptions can happen due to considerations beyond your control, and so you have to handle them.
You must not handle the fatal and boneheaded exceptions. The boneheaded exceptions you don't need to handle because you are never going to do anything that causes them to be thrown. If they are thrown then you have a bug and the solution is fix the bug. Don't handle the exception; that's hiding the bug. And you can't meaningfully handle fatal exceptions because they're fatal. The process is about to go down. You might consider logging the fatal exception, but keep in mind that the logging subsystem might be the thing that triggered the fatal exception in the first place.
In short: handle only those exceptions that can possibly happen that you know how to handle. If you don't know how to handle it, leave it to your caller; the caller might know better than you do.
In your particular case: don't handle any exceptions in this method. Let the caller deal with the exceptions. If the caller passes you an url that cannot be resolved, crash them. If the bad url is a bug then the caller has a bug to fix and you are doing them a favour by bringing it to their attention. If the bad url is not a bug -- say, because the user's internet connection is messed up -- then the caller needs to find out why the fetch failed by interrogating the real exception. The caller might know how to recover, so help them.
First of all, you should, for all practical purposes, never throw type Exception. Always throw something more specific. Even ApplicationException would be better, marginally. Secondly, use separate catch statements for different operations when, and only when, the caller will have reason to care which operation failed. If an InvalidOperationException that occurs at one point in your program will imply something different about the state of your object than one which occurs at some other time, and if your caller is going to care about the distinction, then you should wrap the first part of your program in a 'try/catch' block which will wrap the InvalidOperationException in some other (possibly custom) exception class.
The notion of "only catch exceptions you know how to handle" is nice in theory, but unfortunately most exception types are so vague about the state of underlying objects that it's almost impossible to know whether one can "handle" an exception or not. For example, one might have a TryLoadDocument routine which must internally use methods that might throw exceptions if parts of the document cannot be loaded. In 99% of cases where such an exception occurs, the proper way to "handle" such an exception will be to simply abandon the partially-loaded document and return without exposing it to the caller. Unfortunately, it's very difficult to identify the 1% of cases where that is insufficient. You should endeavor to throw different exceptions in the cases where your routine has failed without doing anything, versus those where it may have had other unpredictable side-effects; unfortunately, you'll probably be stuck guessing at the interpretation of most exceptions from routines you call.
Exception e.message should have more than enough error message data for you to debug it properly. When I do exception handling I generally just logfile it with some short information about where it happened, and the actual exception.
I wouldn't split it like that, that just makes a mess. Exceptions are mostly for YOU. Ideally if your user is causing exceptions you would have caught them earlier.
I wouldn't recommend throwing different named exceptions unless they're not really exceptions (for example sometimes in certain API calls the response becomes null. I'd usually check for that and throw a helpful exception for me).
Look at Unity Interception. Within that framework, you can use something called an ICallHandler, which allows you to intercept calls and do whatever you need/want to do with the intercepted call.
For example:
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
var methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.Exception != null)
{
// exception was encountered...
var interceptedException = methodReturn.Exception
// ... do whatever you need to do, for instance:
if (interceptedException is ArgumentNullException)
{
// ... and so on...
}
}
}
There are other interception frameworks, of course.
Consider splitting the method into smaller ones so error handling can be done for related errors.
You have multiple semi-unrelated things happening in the same method, as result error handling have to be more or less per line of code.
I.e. for your case you can split method into: CreateRequest (handle invalid arguments errors here), GetResponse (handle network errors), ParseRespone (handle content errors).
I do not agree with #oded when he says:
"Rule one of exception handling - do not catch exceptions you don't know how to handle."
It may be OK for academic purposes, but in real life your customers do not want non informative errors popping up on their faces.
I think you can and should catch exceptions and them generate some informative exception to the user. When an nice error, well informative, is shown to the user it can have more information about what he/she should do to solve the problem.
Also, catching all exception can be useful when you decide to log errors or, even better, send them to you automatically.
All my projects have a Error class and I always catch every exception using it. Even though i dont do much on this class, it is there and it can be used to a lot of things.
Related
I'm looking at the article C# - Data Transfer Object on serializable DTOs.
The article includes this piece of code:
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
throw ex;
}
}
The rest of the article looks sane and reasonable (to a noob), but that try-catch-throw throws a WtfException... Isn't this exactly equivalent to not handling exceptions at all?
Ergo:
public static string SerializeDTO(DTO dto) {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
Or am I missing something fundamental about error handling in C#? It's pretty much the same as Java (minus checked exceptions), isn't it? ... That is, they both refined C++.
The Stack Overflow question The difference between re-throwing parameter-less catch and not doing anything? seems to support my contention that try-catch-throw is-a no-op.
EDIT:
Just to summarise for anyone who finds this thread in future...
DO NOT
try {
// Do stuff that might throw an exception
}
catch (Exception e) {
throw e; // This destroys the strack trace information!
}
The stack trace information can be crucial to identifying the root cause of the problem!
DO
try {
// Do stuff that might throw an exception
}
catch (SqlException e) {
// Log it
if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
// Do special cleanup, like maybe closing the "dirty" database connection.
throw; // This preserves the stack trace
}
}
catch (IOException e) {
// Log it
throw;
}
catch (Exception e) {
// Log it
throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
// Normal clean goes here (like closing open files).
}
Catch the more specific exceptions before the less specific ones (just like Java).
References:
MSDN - Exception Handling
MSDN - try-catch (C# Reference)
First, the way that the code in the article does it is evil. throw ex will reset the call stack in the exception to the point where this throw statement is losing the information about where the exception actually was created.
Second, if you just catch and re-throw like that, I see no added value. The code example above would be just as good (or, given the throw ex bit, even better) without the try-catch.
However, there are cases where you might want to catch and rethrow an exception. Logging could be one of them:
try
{
// code that may throw exceptions
}
catch(Exception ex)
{
// add error logging here
throw;
}
Don't do this,
try
{
...
}
catch(Exception ex)
{
throw ex;
}
You'll lose the stack trace information...
Either do,
try { ... }
catch { throw; }
OR
try { ... }
catch (Exception ex)
{
throw new Exception("My Custom Error Message", ex);
}
One of the reason you might want to rethrow is if you're handling different exceptions, for
e.g.
try
{
...
}
catch(SQLException sex)
{
//Do Custom Logging
//Don't throw exception - swallow it here
}
catch(OtherException oex)
{
//Do something else
throw new WrappedException("Other Exception occured");
}
catch
{
System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
throw; //Chuck everything else back up the stack
}
C# (before C# 6) doesn't support CIL "filtered exceptions", which VB does, so in C# 1-5 one reason for re-throwing an exception is that you don't have enough information at the time of catch() to determine whether you wanted to actually catch the exception.
For example, in VB you can do
Try
..
Catch Ex As MyException When Ex.ErrorCode = 123
..
End Try
...which would not handle MyExceptions with different ErrorCode values. In C# prior to v6, you would have to catch and re-throw the MyException if the ErrorCode was not 123:
try
{
...
}
catch(MyException ex)
{
if (ex.ErrorCode != 123) throw;
...
}
Since C# 6.0 you can filter just like with VB:
try
{
// Do stuff
}
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
// Handle, other exceptions will be left alone and bubble up
}
My main reason for having code like:
try
{
//Some code
}
catch (Exception e)
{
throw;
}
is so I can have a breakpoint in the catch, that has an instantiated exception object. I do this a lot while developing/debugging. Of course, the compiler gives me a warning on all the unused e's, and ideally they should be removed before a release build.
They are nice during debugging though.
A valid reason for rethrowing exceptions can be that you want to add information to the exception, or perhaps wrap the original exception in one of your own making:
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
string message =
String.Format("Something went wrong serializing DTO {0}", DTO);
throw new MyLibraryException(message, ex);
}
}
Isn't this exactly equivalent to not
handling exceptions at all?
Not exactly, it isn't the same. It resets the exception's stacktrace.
Though I agree that this probably is a mistake, and thus an example of bad code.
You don't want to throw ex - as this will lose the call stack. See Exception Handling (MSDN).
And yes, the try...catch is doing nothing useful (apart from lose the call stack - so it's actually worse - unless for some reason you didn't want to expose this information).
This can be useful when your programming functions for a library or dll.
This rethrow structure can be used to purposefully reset the call stack so that instead of seeing the exception thrown from an individual function inside the function, you get the exception from the function itself.
I think this is just used so that the thrown exceptions are cleaner and don't go into the "roots" of the library.
A point that people haven't mentioned is that while .NET languages don't really make a proper distinction, the question of whether one should take action when an exception occurs, and whether one will resolve it, are actually distinct questions. There are many cases where one should take action based upon exceptions one has no hope of resolving, and there are some cases where all that is necessary to "resolve" an exception is to unwind the stack to a certain point--no further action required.
Because of the common wisdom that one should only "catch" things one can "handle", a lot of code which should take action when exceptions occur, doesn't. For example, a lot of code will acquire a lock, put the guarded object "temporarily" into a state which violates its invariants, then put it object into a legitimate state, and then release the lock back before anyone else can see the object. If an exception occurs while the object is in a dangerously-invalid state, common practice is to release the lock with the object still in that state. A much better pattern would be to have an exception that occurs while the object is in a "dangerous" condition expressly invalidate the lock so any future attempt to acquire it will immediately fail. Consistent use of such a pattern would greatly improve the safety of so-called "Pokemon" exception handling, which IMHO gets a bad reputation primarily because of code which allows exceptions to percolate up without taking appropriate action first.
In most .NET languages, the only way for code to take action based upon an exception is to catch it (even though it knows it's not going to resolve the exception), perform the action in question and then re-throw). Another possible approach if code doesn't care about what exception is thrown is to use an ok flag with a try/finally block; set the ok flag to false before the block, and to true before the block exits, and before any return that's within the block. Then, within finally, assume that if ok isn't set, an exception must have occurred. Such an approach is semantically better than a catch/throw, but is ugly and is less maintainable than it should be.
While many of the other answers provide good examples of why you might want to catch an rethrow an exception, no one seems to have mentioned a 'finally' scenario.
An example of this is where you have a method in which you set the cursor (for example to a wait cursor), the method has several exit points (e.g. if () return;) and you want to ensure the cursor is reset at the end of the method.
To do this you can wrap all of the code in a try/catch/finally. In the finally set the cursor back to the right cursor. So that you don't bury any valid exceptions, rethrow it in the catch.
try
{
Cursor.Current = Cursors.WaitCursor;
// Test something
if (testResult) return;
// Do something else
}
catch
{
throw;
}
finally
{
Cursor.Current = Cursors.Default;
}
One possible reason to catch-throw is to disable any exception filters deeper up the stack from filtering down (random old link). But of course, if that was the intention, there would be a comment there saying so.
It depends what you are doing in the catch block, and if you are wanting to pass the error on to the calling code or not.
You might say Catch io.FileNotFoundExeption ex and then use an alternative file path or some such, but still throw the error on.
Also doing Throw instead of Throw Ex allows you to keep the full stack trace. Throw ex restarts the stack trace from the throw statement (I hope that makes sense).
In the example in the code you have posted there is, in fact, no point in catching the exception as there is nothing done on the catch it is just re-thown, in fact it does more harm than good as the call stack is lost.
You would, however catch an exception to do some logic (for example closing sql connection of file lock, or just some logging) in the event of an exception the throw it back to the calling code to deal with. This would be more common in a business layer than front end code as you may want the coder implementing your business layer to handle the exception.
To re-iterate though the There is NO point in catching the exception in the example you posted. DON'T do it like that!
Sorry, but many examples as "improved design" still smell horribly or can be extremely misleading. Having try { } catch { log; throw } is just utterly pointless. Exception logging should be done in central place inside the application. exceptions bubble up the stacktrace anyway, why not log them somewhere up and close to the borders of the system?
Caution should be used when you serialize your context (i.e. DTO in one given example) just into the log message. It can easily contain sensitive information one might not want to reach the hands of all the people who can access the log files. And if you don't add any new information to the exception, I really don't see the point of exception wrapping. Good old Java has some point for that, it requires caller to know what kind of exceptions one should expect then calling the code. Since you don't have this in .NET, wrapping doesn't do any good on at least 80% of the cases I've seen.
In addition to what the others have said, see my answer to a related question which shows that catching and rethrowing is not a no-op (it's in VB, but some of the code could be C# invoked from VB).
Most of answers talking about scenario catch-log-rethrow.
Instead of writing it in your code consider to use AOP, in particular Postsharp.Diagnostic.Toolkit with OnExceptionOptions IncludeParameterValue and
IncludeThisArgument
Rethrowing exceptions via throw is useful when you don't have a particular code to handle current exceptions, or in cases when you have a logic to handle specific error cases but want to skip all others.
Example:
string numberText = "";
try
{
Console.Write("Enter an integer: ");
numberText = Console.ReadLine();
var result = int.Parse(numberText);
Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
if (numberText.ToLowerInvariant() == "nothing")
{
Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}
else
{
throw;
}
}
finally
{
Console.WriteLine("Freed some resources.");
}
Console.ReadKey();
However, there is also another way of doing this, using conditional clauses in catch blocks:
string numberText = "";
try
{
Console.Write("Enter an integer: ");
numberText = Console.ReadLine();
var result = int.Parse(numberText);
Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}
finally
{
Console.WriteLine("Freed some resources.");
}
Console.ReadKey();
This mechanism is more efficient than re-throwing an exception because
of the .NET runtime doesn’t have to rebuild the exception object
before re-throwing it.
I use following code to read data from XML
var temp = default(T);
var serializer = new XmlSerializer(typeof(T));
try
{
TextReader textReader = new StreamReader(fileName);
temp = (T)serializer.Deserialize(textReader);
}
catch (InvalidOperationException ioe)
{
throw;
}
I know that rethorow it is redundant part, but I wanted to throw it in controled way. I want to use this place to show the user that some XML file has been corupted (ie tag was not closed). Everything works fine until I don't leave the class and I want to catch this exception from the class which request this data. It seems that the exception is missinig and bypassed somehow, and application jump into diffrent method suddenly. Why I cannot catch this exception? I even create my own exception, but the result was the same - it seems that it just not leave original class and cause some application jump.
xml deserialization exceptions work just like any other exceptions - there are no surprises (other than it is even more important than usual to check the .InnerExceptions (recursively), because all the interesting information is nested a few exceptions down).
Is this perhaps simply that you are catching the wrong kind of exception? For example, there is no guarantee it is an InvalidOperationException. As long as the calling method has a try with a catch(Exception ex), it should catch any exception that happens during deserialization.
I found the reason. Method which throw that exception was called by static class constructor. And it was why exception wasn't thrown up. Static constructors are called on the begining and they just don't throw exceptions (do they?). I changed original code by extracting method from xonstructor and by calling it manualy - now I can catch exception in above layer.
you can use XSD to validate that, there is the only way dynamic that i know to make this kind of validation, this Link could help
You can find the entire source here, if you want to share some more
pointers:
https://github.com/sergiotapia/DreamInCode.Net
Basically my API is going to give other developers an easy way to access information from http://www.dreamincode.net - and in one of the methods in my library, I wrote this code:
public UserProfile FindUserById(int id)
{
if (id <= 0)
throw new ArgumentOutOfRangeException("id", id, "The user ID must be greater than 0.");
string xmlEndPoint = string.Format("http://www.dreamincode.net/forums/xml.php?showuser={0}", id.ToString());
string xmlResponse;
using (WebClient client = new WebClient())
{
try
{
xmlResponse = client.DownloadString(xmlEndPoint);
}
catch (Exception e)
{
throw new Exception("Error: " + e.InnerException);
}
}
if (String.IsNullOrEmpty(xmlResponse))
throw new Exception("Error: The XML endpoint did not respond.");
return UserParser.ParseUser(xmlResponse);
}
Am I doing this the best way possible with respects to usefulness to other users? Would the .InnerException be enough for other devs to know what went wrong?
Thank you for your time. :)
Edit:
So following your advice, I wrote:
using (WebClient client = new WebClient())
{
try
{
xmlResponse = client.DownloadString(xmlEndPoint);
}
catch (Exception e)
{
throw new Exception("Error: Something went wrong, please check the InnerException.", e);
}
}
Is this the way to go? Is this preserving the stack trace? Am I doing it right?
Edit 2:
So this is the ideal solution?
//Just let it explode?
using (WebClient client = new WebClient())
{
xmlResponse = client.DownloadString(xmlEndPoint);
}
Don't throw Exception. Instead, throw an appropriate derived type.
Don't wrap exceptions (throwing from a catch) unless you have additional details to provide.
(such as what page it failed on, or why you think it failed)
When wrapping exceptions, always pass the original exception as the InnerException constructor parameter. This provides access to the original stack trace, and any additional information in the exception.
A few guidelines
Don't throw Exception - it's too generic.
Don't rethrow an exception using throw ex; - it discards the call stack.
Do throw the ArgumentOutOfRangeException if the wrong parameters are passed
Consider catching and wrap exceptions thrown by the code you call. If there is one, use a predefined Exception type that's a good match, otherwise define your own. Never discard a caught exception unless you're trying to make it hard to debug.
Consider include additional context about the exception so that the fault can be traced
Consider mentioning the inner exception in your exception message, so that other developers are reminded to look ("An {0} error occurred while downloading {1}; see inner exception for details")
Update
To address Scott's comments below on context.
If the request to find a particular user fails, it can be useful to wrap the original exception in another that provides more context:
try
{
...
}
catch (Exception e)
{
// Yes, catch every exception
var message
= string.Format(
"Failed to load user profile for user {0}: {1} ({2})",
id,
e.GetType().Name,
"see inner exception for details");
throw new InvalidOperationException(message, e);
}
This is useful because the actual error may only occur for a particular user id (for example, if the data for this particular user has been corrupted in the underlying database). Providing this kind of additional context provides more information for the developer trying to debug the problem.
Some suggestions:
If the existing .NET exceptions fit your needs, use them. The ArgumentOutOfRangeException seems appropriate in your example.
Otherwise, simply create a new exception class and include whatever additional data is needed to accurately describe the error.
Consider whether upper layers of code need to "filter" exceptions in some way (i.e. catch some and let others continue unwinding). If yes, you may want to consider designing your own exception inheritance hierarchy, so exceptions may be easily filtered by type.
In any case, try to be more specific than just plain Exception.
Consider whether exception messages can "bubble-up" all the way to the end user. This may or may not be a good idea depending on circumstances.
If you (or rather, clients of your API) let user see exception messages, consider localizing them.
Document your exceptions. You can use <exception> tag in ///-style comments to do so.
The answer provided by SLaks covers most of your issues/concerns. As mentioned, you should rarely (if ever) throw a general Exception and you should rarely (if ever) simply wrap an existing exception and throw a new one. The problem with the code you have here
using (WebClient client = new WebClient())
{
try
{
xmlResponse = client.DownloadString(xmlEndPoint);
}
catch (Exception e)
{
throw new Exception("Error: " + e.InnerException);
}
}
is that the consumers of your API will be required to catch Exception and then inspect the InnerException for the actual details of what went wrong. Instead, if you just wrote the code like
using (WebClient client = new WebClient())
{
xmlResponse = client.DownloadString(xmlEndPoint);
}
any API consumer would see the actual (probably more meaningful) exception that was thrown by the WebClient call.
All of that being said, if the idea behind your API is to hide the fact that when a user calls FindUserById they are actually going out and hitting a web service somewhere and any exceptions thrown by the WebClient call would actually be more "noise" (or otherwise be more confusing to your API consumers) then it is acceptable to catch the exception and throw a more meaningful one (making sure to provide the original exception in the InnerException). However, since you are effectively throwing two exceptions (ArgumentOutOfRangeException and Exception) your API consumers aren't really getting a more meaningful exception.
The ArgumentOutOfRangeException is appropriate (although if you are using .NET 4 you should really be using the Code Contracts stuff in which case your argument check really should just be a Contract.Requires<ArgumentOutOfRangeException>(id > 0, "The user ID must be greater than 0.");. The general Exception throws should either be removed or replaced with a more meaningful exception type.
I've got some UI code that looks like this:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch (Exception exception)
{
// Content wasn't created, show a message, stop processing
return;
}
It seems the try catch was added because the constructor for SomeClass would bomb out if the someId it receives isn't valid, and data couldn't be found in a DB.
Running this code through FXCop recently, it warns against using the general Exception, but all SomeClass does is throw a new Exception with a message to say it failed to initialize.
I guess the problem is that the class constructor should have it's own custom exception, which I could then handle in my UI, but I wonder what else I could do to the code above to handle the exception, that meets FXCop requirements?
FxCop's rule exists because the catch (Exception) block above catches all possible exceptions, including low-level exceptions like StackOverflowException that you probably can't catch in a useful way.
The right approach is definitely to throw a more specific type: either one you've invented, or an existing .NET framework exception type that closely matches your situation. (When in doubt, I normally go for InvalidOperationException.)
Alternatively, you could check the exact exception type when catching it. This won't prevent the FxCop warning, but it should address the underlying problem:
catch (Exception exception)
{
if (exception.GetType() == typeof(Exception))
{
// Content wasn't created, show a message, stop processing
return;
}
else
{
// Some other exception type that wasn't thrown from our code -
// delegate to a higher-level exception handler
throw;
}
}
You don't need a custom exception; just use one of the dozens that already exist in the framework for given circumstances. If someId is bad, throw an ArgumentException -- that's what it's made for. If something's null that shouldn't be, a NullReferenceException will occur; just let it be thrown. Etc. Throwing a plain Exception is a bit like saying "something went wrong -- read the message for details" rather than "this went wrong".
FxCop is complaining about catch (Exception) because it's too commonly abused to swallow up all exceptions rather than letting them propagate and be handled by code that knows how to do so. You should be able to say what types of exceptions are being thrown and catch those, while letting those you don't recognize make their way up the call stack.
You should fix the class constructor. Throwing Exception is never a good idea.
However, to work around the issue you have temporarily (as this is a horrible, unreliable hack), you could check the message of the exception against the one you're expecting:
catch (Exception exception)
{
if (exception.Message == "whatever your class sets the message to")
// Content wasn't created, show a message, stop processing
return;
else
// Any other exception should bubble
throw;
}
Using InvalidOperationException in place of throwing Exception sounds like it might be sensible.
If FXCop doesn't like handling the general Exception (and I tend to agree) then maybe you have access to SomeClass's source code. Modify the constructor to throw an exception that is more specific, e.g. ArgumentOutOfRangeException or some custom exception.
In that case your code would then look as follows:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch(ArgumentOutOfRangeException exception)
{
// Content wasn't created, show a message, stop processing
return;
}
As many others have said, the constructor should not be throwing a naked Exception. Seeing that the constructor retrieves data from DB and throws based on the result, the best solution is to create your own exception class.
Creating exceptions is super-easy in Visual studio. Just type in Exception and press TAB. It will then create the exception class with required constructors(all four of them). Do not be afraid to create classes that don't do very much, that's what they are designed for.
This is how I would write this class:
public class SomeClass {
public SomeClass(int someId) {
if (someId < 0) //validation on the ID, can it be negative?
throw new ArgumentException("someId", "ID cannot be negative");
//Perform DB operation
if (/*DB error - not found*/)
throw new DataNotFoundException("Cannot find record with ID " + someId);
}
}
[Serializable]
public class DataNotFoundException : Exception {
public DataNotFoundException() { }
public DataNotFoundException(string message) : base(message) { }
public DataNotFoundException(string message, Exception inner) : base(message, inner) { }
protected DataNotFoundException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
Suppose I have the following two classes in two different assemblies:
//in assembly A
public class TypeA {
// Constructor omitted
public void MethodA
{
try {
//do something
}
catch {
throw;
}
}
}
//in assembly B
public class TypeB {
public void MethodB
{
try {
TypeA a = new TypeA();
a.MethodA();
}
catch (Exception e)
//Handle exception
}
}
}
In this case, the try-catch in MethodA just elevates the exception but doesn't really handle it. Is there any advantage in using try-catch at all in MethodA? In other words, is there a difference between this kind of try-catch block and not using one at all?
In your example, there is no advantage to this. But there are cases where it is desirable to just bubble up a specific exception.
public void Foo()
{
try
{
// Some service adapter code
// A call to the service
}
catch (ServiceBoundaryException)
{
throw;
}
catch (Exception ex)
{
throw new AdapterBoundaryException("some message", ex);
}
}
This allows you to easily identify which boundary an exception occurred in. In this case, you would need to ensure your boundary exceptions are only thrown for code specific to the boundary.
Yes there is a difference. When you catch an exception, .NET assumes you are going to handle it in some way, the stack is unwound up to the function that is doing the catch.
If you don't catch it will end up as an unhandled exception, which will invoke some kind of diagnostic (like a debugger or a exception logger), the full stack and its state at the actual point of failure will be available for inspection.
So if you catch then re-throw an exception that isn't handled elsewhere you rob the diagnostic tool of the really useful info about what actually happened.
With the code the way you've written it for MethodA, there is no difference. All it will do is eat up processor cycles. However there can be an advantage to writing code this way if there is a resource you must free. For example
Resource r = GetSomeResource();
try {
// Do Something
} catch {
FreeSomeResource();
throw;
}
FreeSomeResource();
However there is no real point in doing it this way. It would be much better to just use a finally block instead.
Just rethrowing makes no sense - it's the same as if you did not do anything.
However it gets useful when you actually do something - most common thing is to log the exception. You can also change state of your class, whatever.
Taken as-is, the first option would seem like a bad (or should that be 'useless'?) idea. However, it is rarely done this way. Exceptions are re-thrown from within a Catch block usually under two conditions :
a. You want to check the exception generated for data and conditionally bubble it up the stack.
try
{
//do something
}
catch (Exception ex)
{
//Check ex for certain conditions.
if (ex.Message = "Something bad")
throw ex;
else
//Handle the exception here itself.
}
b. An unacceptable condition has occurred within a component and this information needs to be communicated to the calling code (usually by appending some other useful information or wrapping it in another exception type altogether).
try
{
//do something
}
catch (StackOverflowException ex)
{
//Bubble up the exception to calling code
//by wrapping it up in a custom exception.
throw new MyEuphemisticException(ex, "Something not-so-good just happened!");
}
Never do option A. As Anton says, it eats up the stack trace. JaredPar's example also eats up the stacktrace. A better solution would be:
SomeType* pValue = GetValue();
try {
// Do Something
} finally {
delete pValue;
}
If you got something in C# that needs to be released, for instance a FileStream you got the following two choices:
FileStream stream;
try
{
stream = new FileStream("C:\\afile.txt");
// do something with the stream
}
finally
{
// Will always close the stream, even if there are an exception
stream.Close();
}
Or more cleanly:
using (FileStream stream = new FileStream("c:\\afile.txt"))
{
// do something with the stream
}
Using statement will Dispose (and close) the stream when done or when an exception is closed.
When you catch and throw, it allows you to set a breakpoint on the throw line.
Re-throwing exceptions can be used to encapsulate it into generic exception like... consider following example.
public class XmlException: Exception{
....
}
public class XmlParser{
public void Parse()
{
try{
....
}
catch(IOException ex)
{
throw new XmlException("IO Error while Parsing", ex );
}
}
}
This gives benefit over categorizing exceptions. This is how aspx file handlers and many other system code does exception encapsulation which determines their way up to the stack and their flow of logic.
The assembly A - try catch - block does not make any sense to me. I believe that if you are not going to handle the exception, then why are you catching those exceptions.. It would be anyway thrown to the next level.
But, if you are creating a middle layer API or something like that and handling an exception ( and hence eating up the exception) in that layer does not make sense, then you can throw your own layer ApplicationException. But certainly rethrowing the same exception does not make sense.
Since the classes are in 2 different assemblies, you may want o simply catch the exception for logging it and then throw it back out to the caller, so that it can handle it the way it sees fit. A throw instead of a throw ex will preserve contextual information about where the exception originated. This can prove useful when your assembly is an API/framework where in you should never swallow exceptions unless its meaningful to do so but helpful nonetheless in trouble shooting if it's logged for example to the EventLog.
You can use try{} catch(ex){} block in Method A only if you could catch the specific exception which can be handled in MethodA() (for eg: logging ).
Another option is chain the exception using the InnerException property and pass it to the caller. This idea will not kill the stack trace.