I'm trying to find an answer on that question, which is:
Is the following code is a good practice?
Should I try to reproduce it wherever it's possible or not? and if not, why?
public class ExceptionHelper
{
private static readonly HttpException _errorReadingRequest = new HttpException(500, "Error reading request. Buffer is empty.");
public static Exception ErrorReadingRequest { get { return _errorReadingRequest; } }
}
public class ExceptionThrower
{
public static void ThrowCached1()
{
throw ExceptionHelper.ErrorReadingRequest;
}
// ...
}
I've tried to throw in several places the cached instances and it seems to preserve the stack trace, from MSDN,
The stack trace begins at the statement where the exception is thrown
and ends at the catch statement that catches the exception. Be aware
of this fact when deciding where to place a throw statement.
I understand that as "It stores the stack trace at the throw, not at the creation". However, I'm wondering if there could be a problem when multiple threads try to throw the same cached instance of exception.
On the same MDSN page, they are using an helper function and it seems in the framework, they are doing the same: helper function which recreates the exception and throw.
Note: I know it's not a common case because most of the time, you want a specific message to be stored in the exception so it's easier to understand what's happening.
Maybe the question is just is throw keyword thread safe or not?
Context:
I've stumble upon this kind of code, while code reviewing some performance touchy application code. The goal is to create the maximum of instance during startup and then never (or almost never) instances during execution, in order to limit the GC performance impact (especially because of heap fragmentation occuring with GCHandle thing). I had a bad feeling about this code but needed facts to support my refactoring.
Generally it makes no sense to have one cached exception. CREATING an object is fast. Exceptions shoudl be rare - and catching them has some overhead, as has throwing them. THere is simply nothing gained from having "one exception to rule them all", except:
Threading issues
More convoluted code
Totally ignoring coding standards I have seen in the last 20 years.
If any of those things are your goal - go along.
Maybe the question is just is throw keyword thread safe or not ?
The throw keyword is thread safe - you can have multiple threads throwing at the same time. Using the same exception though is going to get you into trouble, but it is not because the throw KEYWORD is not thread safe but because you maliciously violate thread safety by passing in the same data object.
Throwing an exception mutates that exception object. It stores the stack for example. This is a problem if you want to use the stack trace for logging purposes. You'll get randomly corrupted stacks.
Also, creating an exception object is cheap. This does not accomplish much.
#TomTom gave a great answer, I want just to point out the example for exception caching being a standard practice: TPL's Task class Exception property.
Sometimes, if the exception is thrown inside some asynchronous operation, it is a good practice to save the information about it for the moment you need the result of operation.
But! As TPL's programmers did, you should wrap the original exception inside the new one (for example, AggregateException) so you can see the original source and stacktrace of it.
As for the GC collection's performance hit, you can use other techniques. For example, if there are a lot of objects being created and after that being collected, try to use the structs for DTO-objects instead of classes. If they will fit into a stack size, they will be collected automatically after the method ends it's execution.
Related
I would like to return exceptions from a method, like this:
Exception f()
{
try
{
// Do something.
return null;
}
catch(Exception e)
{
return e;
}
}
I know that this is considered bad practice, but are there any technical reasons to avoid this?
EDIT: This is not the same question as Is it bad practice to return Exceptions from your methods. I am asking about technical reasons, not best practices.
There are no 'technical' reasons to avoid this. That is, the .Net framework will happily support this type of arrangement.
Also be aware that throwing exceptions incurs a performance penalty, so avoid relying on throwing exceptions for your normal control flow. They should only be used when something has genuinely gone wrong.
It's also fine to instantiate an exception without throwing it:
Exception f()
{
return new Exception("message");
}
Here are some reasons that you may want to rethink that design.
Firstly, new ArgumentOutOfRangeException(...); does not produce your exception stack trace is not generated until you throw it. This may confuse debugging efforts further down the stack. The stack trace will literally be lying.
Secondly, Exception is heavier than some sort of status enum to indicate what type of error occurred. It is hard to see what benefit you are getting out of the response object being of type exception. It presumably requires the caller to subsequently perform a bunch of if (response is FileNotFoundException) .... and decide what they want to do for each.
This means that you lose the ability to differentiate between expected exceptions and unexpected exceptions in a given function. Take a well understood unique constraint violation. Somewhere within your call, or something you call, an insert statement is rejected by the DBMS because of another record having this value. Depending on your use case, this is either an exceptional circumstance indicating something somewhere went very wrong (eg, a corrupt data file), or a result in its own right (eg, a booking system that allocated a seat to someone else between showing you its availability and you accepting). In the first case, you would want your caller to bubble that up to the point in the application which knows what to do about that. In the second, you can safely return that for the caller to do its business.
Thirdly, it is a violation of the principle of least astonishment. Exceptions, by design, are bail out by default. Unless I explicitly catch an exception, it will bail out of my method, excecuting the stuff in my except and finally blocks, nicely calling dispose for me at the end of any using blocks and repeat in my method's caller. What it will never do is execute the code of mine that might be relying on the results of that method call.
Your design here is ignore by default. Unless I explicitly check the result and choose to throw, it will carry on executing my code. Consider this contrived example:
Exception error;
error = GetData(out data);
if (error is DbException) return error;
if (error is ArgumentOutOfRangeException) return error;
// if (error is ....... etc
error = ApplyChangesToData(data);
// if (error is ....... etc
error = SaveData(data);
// if (error is ....... etc
Now the stakes are high if I miss something, because my partially constructed data object may then make its way through the ApplyChangesToData method and then get saved back to the database in corrupted form. This could be as simple as you not anticipating that internally GetData hits a SocketException or an OutOfMemoryException. It isn't just making your abstraction a bit leaky, it means that unless you do have a leaky abstraction, your code cannot be safely written. My code has to know whether you are talking to SqlServer or Oracle or Mongo or whatever so I can anticipate all the possible exceptions you may retun and include them in my if lines. Of course I could put an else in and throw any exception object, but presumably you don't want to do this or you wouldn't be catching it in the first place.
On the other hand, if you were allowing the exceptions to bubble up, and I was confident in what such an exception meant in my context and could still meaningfully carry on, I still have the option of catching that exception and reacting to or suppressing it.
The only exception (pun unintended) that I can think of is at the edge of an API service layer, where you might want to log the exception then return a generic "something went wrong on the server" rather than blab your dirty laundry and expose security sensitive information over a public facing endpoint.
I hope I have convinced you (or , if not, at least someone in the future reading this suggestion) not to go down that dragon-filled path.
I recently implemented a function which logs object contents using JSON.SerializeObject.
To cut a long story short, the idea was, that this function would be used in our newly implemented logging mechanism, to track objects when needed, based on system parameterization.
One absolute requirement for the entire logging mechanism, was that it should never throw exceptions, because it would be used extensively. Any developer should be able to use it and under no circumstances should this function cause any interruption in code flow. In case of failure, any call should simply be skipped.
After implementing it and having inspected and handled every exception that I could think of, I decided to wrap the entire functionality in an outer try-catch block, just in case.
Like so:
public static void TrackObject(object obj)
{
try { Console.WriteLine(JsonConvert.SerializeObject(obj)); }
catch { Console.WriteLine("Failed to track object."); }
}
After passing all tests with flying colors, I fired up the main application to do some actual environment testing.
To my surprise, due to a Nuget misconfiguration, my function caused an exception (System.IO.FileLoadException) after it was called, but before it entered the try-catch block and so it propagated back to the main application, causing havoc to code flow.
This got me thinking.
There are ways for exceptions to be thrown while calling the function but before a handler kicks in. There are also cases where an exception is simply unacceptable.
My current solution, was to create a wrapper function, which simply calls the actual function inside a try-catch. But this looks ugly and wrong. Plus I am not sure it is a bullet proof solution.
public static void TrackObject(object obj)
{
try { PrivateTrackObject(obj); }
catch { Console.WriteLine("Failed to track object."); }
}
private static void PrivateTrackObject(object obj)
{
Console.WriteLine(JsonConvert.SerializeObject(obj));
}
Is there a way to create a bullet-proof, no-way in hell, exception free method?
Or at least is there a definitive list of exceptions that can occur on a method call?
PS. The compiler warned me about the version mismatch, but I didn’t see it the first time.
PS2. I have created a sample project for anyone who wishes to see this issue in action.
https://drive.google.com/open?id=15BDrLNn87gsMHc9pQ-TgyDMSLQxDBq18
Is there a way to create a bullet-proof, no-way in hell, exception free method?
No. Even if the method is literally empty you can always have a thread abort exception thrown, or a stack overflow exception if there isn't enough space on the stack to call that method, or it could result in an out of memory exception.
is there a definitive list of exceptions that can occur on a method call?
If it's arbitrary code (i.e. from a delegate) then no. It could always be a custom exception of some type that didn't even exist when you wrote your code.
Also note that in your situation you need to be concerned about any possible exceptions that could be thrown in your catch block, if you just want to try handling normal exceptions (unlike the ones mentioned above) that happen in your try block. Just logging the exception could fail. In your example of using the console there could be problems with standard output that result in an exception. If you're really going for this code never throws you'd need to try to log the exceptions, but have other backup logging options for when they aren't working (and if you really can't throw, which as mentioned by others, is almost certainly a bad idea, then you need to be willing to go on without logging if logging your exceptions is failing).
Can you use a throw or try-catch within a constructor?
If so, what is the purpose of having a constructor that has an argument that can throw an exception?
This constructor is an example:
public Chat()
{
chatClient = new Client(Configuration.LoginEmail, Configuration.LoginPassword);
chatRoom = chatClient.JoinRoom(Configuration.RoomUrl);
}
The line chatRoom = chatClient.JoinRoom(Configuration.RoomUrl); can throw exceptions.
Throwing an exception when appropriate is part of a constructor's job.
Let's consider why we have constructors at all.
One part is convenience in having a method that sets various properties, and perhaps does some more advanced initialisation work (e.g. a FileStream will actually access the relevant file). But then if it was really that convenient all the time we wouldn't sometimes find member initialisers convenient.
The main reason for constructors is so that we can maintain object invariants.
An object invariant is something we can say about an object at the beginning and end of every method call. (If it was designed for concurrent use we would even have invariants that held during method calls).
One of the invariants of the Uri class is that if IsAbsoluteUri is true, then Host will be string that is a valid host, (if IsAbsoluteUri is false Host might be a valid host if it's scheme-relative, or accessing it might cause an InvalidOperationException).
As such when I'm using an object of such a class and I've checked IsAbsoluteUri I know I can access Host without an exception. I also know that it will indeed be a hostname, rather than e.g. a short treatise on mediaeval and early-modern beliefs in the apotropaic qualities of bezoars.
Okay, so some code putting such a treatise in there isn't exactly likely, but code putting some sort of junk into an object certainly is.
Maintaining an invariant comes down to making sure that the combinations of values the object holds always make sense. That has to be done in any property-setter or method that mutates the object (or by making the object immutable, because you can never have an invalid change if you never have a change) and those that set values initially, which is to say in a constructor.
In a strongly typed language we get some of the checking from that type-safety (a number that must be between 0 and 15 will never be set to "Modern analysis has found that bezoars do indeed neutralise arsenic." because the compiler just won't let you do that.) but what about the rest?
Consider the constructors for List<T> that take arguments. One of them takes an integer, and sets the internal capacity accordingly, and the other an IEnumerable<T> that the list is filled with. The start of these two constructors are:
public List(int capacity)
{
if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", capacity, SR.ArgumentOutOfRange_NeedNonNegNum);
/* … */
public List(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
So if you call new List<string>(-2) or new List<int>(null) you get an exception, rather than an invalid list.
An interesting thing to note about this case, is that this is a case where they could possibly have "fixed" things for the caller. In this case it would have been safe to consider negative numbers as the same as 0 and null enumerables as the same as an empty one. They decided to throw anyway. Why?
Well, we have three cases to consider when writing constructors (and indeed other methods).
Caller gives us values we can use directly.
Eh, use them.
Caller gives us values we can't meaningfully use at all. (e.g. setting a value from an enum to an undefined value).
Definitely throw an exception.
Caller gives us values we can massage into useful values. (e.g. limiting a number of results to a negative number, which we could consider as the same as zero).
This is the trickier case. We need to consider:
Is the meaning unambiguous? If there's more than one way to consider what it "really" means, then throw an exception.
Is the caller likely to have arrived at this result in a reasonable manner? If the value is just plain stupid, then the caller presumably made a mistake in passing it to the constructor (or method) and you aren't doing them any favours in hiding their mistakes. For one thing, they're quite likely making other mistakes in other calls but this is the case where it becomes obvious.
If in doubt, throw an exception. For one thing if you're in doubt about what you should do then it's likely the caller would be in doubt about what they should expect you to do. For another it's much better to come back later and turn code that throws into code that doesn't than turn code that doesn't throw into code that does, because the latter will be more likely to turn working uses into broken applications.
So far I've only looked at code that can be considered validation; we were asked to do something silly and we refused. Another case is when we were asked to do something reasonable (or silly, but we couldn't detect that) and we weren't able to do it. Consider:
new FileStream(#"D:\logFile.log", FileMode.Open);
There's nothing invalid in this call that should definitely fail. All validation checks should pass. It will hopefully open the file at D:\logFile.log in read mode and give us a FileStream object through which we can access it.
But what if there's no D:\logFile.log? Or no D:\ (amounts to the same thing, but the internal code might fail in a different way) or we don't have permission to open it. Or it's locked by another process?
In all of these cases we're failing to do what is asked. It's no good our returning an object that represents attempts to read a file that are all going to fail! So again, we throw an exception here.
Okay. Now consider the case of StreamReader() that takes a path. It works a bit like (adjusting to cut out some indirection for the sake of example):
public StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
{
if (path==null || encoding==null)
throw new ArgumentNullException((path==null ? "path" : "encoding"));
if (path.Length==0)
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
Contract.EndContractBlock();
Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, true);
Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false);
}
Here we've got both cases where a throw might happen. First we've got validation against bogus arguments. After that we've a call to the FileStream constructor that in turn might throw an exception.
In this case the exception is just allowed to pass through.
Now the cases we need to consider are a tiny bit more complicated.
With most of the validation cases considered at the beginning of this answer, it didn't really matter in what order we did things. With a method or property we have to make sure that we've either changed things to be in a valid state or thrown an exception and left things alone, otherwise we can still end up with the object in an invalid state even if the exception was thrown (for the most part it suffices to do all of your validation before you change anything). With constructors it doesn't much matter what order things are done in, since we're not going to return an object in that case, so if we throw at all, we haven't put any junk into the application.
With the call to new FileStream() above though, there could be side-effects. It's important that it is only attempted after any other case that would throw an exception is done.
For the most part again, this is easy to do in practice. It's natural to put all of your validation checks first, and that's all you need to do 99% of the time. An important case though is if you are obtaining an unmanaged resource in the course of a constructor. If you throw an exception in such a constructor then it will mean the object wasn't constructed. As such it won't be finalised or disposed, and as such the unmanaged resource won't be released.
A few guidelines on avoiding this:
Don't use unmanaged resources directly in the first place. If at all possible, work through managed classes that wrap them, so it's that object's problem.
If you do have to use an unmanaged resource, don't do anything else.
If you need to have a class with both an unmanaged resource and other state, then combine the two guidelines above; create a wrapper class that only deals with the unmanaged resource and use that within your class.
Better yet, use SafeHandle to hold the pointer to the unmanaged resource if at all possible. This deals with a lot of the work for point 2 very well.
Now. What about catching an exception?
We can certainly do so. The question is, what do we do when we've caught something? Remember that we have to either create an object that matches what we were asked for, or throw an exception. Most of the time if one of the things we've attempted in the course of that fails, there isn't anything we can do to successfully construct the object. We're likely therefore to just let the exception pass through, or to catch an exception just to throw a different one more suitable from the perspective of someone calling the constructor.
But certainly if we can meaningfully continue on after a catch then that's allowed.
So in all, the answer to "Can you use a throw or try and catch within a constructor?" is, "Yes".
There is one fly in the ointment. As seen above the great thing about throwing within a constructor is that any new either gets a valid object or else an exception is thrown; there's no in between, you either have that object or you don't.
A static constructor though, is a constructor for the class as a whole. If an instance constructor fails, you don't get an object but if a static constructor fails you don't get a class!
You're pretty much doomed in any future attempt to make use of that class, or any derived from it, for the rest of the life of the application (strictly speaking, for the rest of the life of the app domain). For the most part this means throwing an exception in a static class is a very bad idea. If it's possible that something attempted and failed might be attempted and succeed another time, then it shouldn't be done in a static constructor.
About the only time when you want to throw in a static constructor is when you want the application to totally fail. For example, it's useful to throw in a web application that lacks a vital configuration setting; sure, it's annoying to have every single request fail with the same error message, but that means you're sure to fix that problem!
Can you use a throw or try and catch within a constructor?
Both are possible.
If an exception can happen during construction of an object instance, and there is something you can do about it, catch it and try to fix it.
If there is nothing you can do about the exception, it is generally best to allow it to propagate (rather than leaving the object instance in an improperly initialized state).
The normal lifecycle of an object is interrupted if an exception is thrown in a instance constructor. So if the object has a destructor to clean up any resources then an exception thrown in the constructor will prevent the destructor running and thus forms a memory leak. Always catch, clean up, and re-throw if you have any disposable resources allocated in the constructors or for any fields.
If an exception is thrown in a static constructor then the class is no longer in a state that can be used by the AppDomain. So always catch exceptions in static constructors and deal with them. Do not re-throw and do not leave them uncaught.
Catching and handling exceptions in any constructor is fine to do.
But as per normal, it is 1000x better to code to avoid exceptions rather than let them occur.
See MSDN Constructor Design & Eric Lippert's Vexing Exceptions.
Let's say I have the following code:
private delegate void DeadlyDelegate();
private void Deadly()
{
throw new Exception("DIE!");
}
public void DoStuff()
{
DeadlyDelegate d = Deadly;
d.BeginInvoke(null, null);
}
Now, there has already been much discussion about if EndInvoke() is needed (and the answer is yes), so I'm not asking that. But let's say that for whatever reason, EndInvoke is never reached (in my example, I simply don't call it, but we could imagine other reasons of how it could accidentally not ever be called).
First question: What happens to the exception? Does it completely disappear and never cause problems? Or does it finally get thrown as an unhandled exception during garbage collection, the same way that Task exceptions do if they are never observed? I've done much searching, both Google and SO, and haven't found the answer to this.
In my own code, I of course plan to always call EndInvoke(). But it would be nice to know what happens if, because of some unanticipated program path, EndInvoke somehow isn't called. I don't want my whole app to come crashing to a halt because of the unhandled exception (if there is one).
Second question: Whatever is the answer to the first question, is the same true of the built-in async calls in the .NET framework, like TcpClient.BeginConnect()? If that method throws an exception, will it simply disappear if I never call EndConnect(), or can it still cause problems?
Third question: (this should be trivial, but thought I'd double check) Is there any way some sort of strange unhandled/unobserved exception can happen in the async code between the BeginInvoke/Connect and EndInvoke/Connect calls? Or am I always guaranteed any exceptions will safely propagate to the point where EndInvoke/Connect is called?
What is the best practice for handling exceptions without having to put try/catch blocks everywhere?
I had the idea of creating a class that is devoted to receiving and handling exceptions, but I am wondering if its a good design idea. Such a class would receive an exception and then decide what to do with it depending on its type or error code, could even parse the stack trace for specific information, etc.
Here is the basic idea behind and implementation:
public class ExceptionHandler
{
public static void Handle(Exception e)
{
if (e.GetBaseException().GetType() == typeof(ArgumentException))
{
Console.WriteLine("You caught an ArgumentException.");
}
else
{
Console.WriteLine("You did not catch an exception.");
throw e; // re-throwing is the default behavior
}
}
}
public static class ExceptionThrower
{
public static void TriggerException(bool isTrigger)
{
if (isTrigger)
throw new ArgumentException("You threw an exception.");
else
Console.WriteLine("You did not throw an exception.");
}
}
class Program
{
static void Main(string[] args)
{
try
{
ExceptionThrower.TriggerException(true);
}
catch(Exception e)
{
ExceptionHandler.Handle(e);
}
Console.ReadLine();
}
}
I thought this would be an interesting endeavor because you would theoretically only need one or very few try / catch blocks around your main() method calls, and let the exception class handle everything else including re-throwing, handling, logging, whatever.
Thoughts?
There is actually a good reason why you don't see similar designs in production code.
First of all, such a design cannot help you reduce the count of try/catch pairs in your code (this should be obvious). It could help you reduce the number of catch statements for a given try, since you could just catch System.Exception and forward to the ExceptionHandler...
But what next?
Every exception needs to be handled differently. How would the ExceptionHandler know exactly what to do? You could try to solve this in a number of ways, e.g.:
Derive from ExceptionHandler and put the code to handle exceptions in virtual methods
Pass a number of Action<Exception> instances to the handler and have it invoke the proper one
Solution (1) would be worse than what you had before: now you need to create a whole new class for each try block and override a bunch of methods to end up with something worse than you had before (it's not immediately clear how the code in a particular class fits in the flow of your program). It would also leave another important question unanswered: you may need context (access to variables in the current scope) to properly handle the exception. How will you provide access to this context?
Solution (2) would actually end up quite similar to writing the catch blocks that we 've been wanting to avoid (each Action would be effectively the contents of a catch block). We end up doing the same thing, only in a more complicated and verbose manner.
There are also other issues:
What should ExceptionHandler do if it cannot handle the exception? Throwing it again will cause you to lose the original stack trace, in effect destroying all the good information in there.
What if there's a bug in ExceptionHandler? You can truse a try/catch. Can you trust code you wrote yourself to the same degree?
As for the ExceptionThrower... what benefit could it possibly offer over throw new Exception();?
Exception handling is a complicated matter already, and it's difficult enough to get it right without adding extra gears to the machine. Especially if they don't buy you anything new. Don't do it.
OK, this is probably not the answer you want but...
I am generally allergic towards the idea of a general exception handling class. You can almost hear how it is a contradiction in itself. An exception is an exceptional event. Exceptional events cannot be handled in a general manner, but needs tailored handling wherever they may appear, which essentially means that your code should to two things:
be defensive about any input in order to avoid exceptions in the first place
put try..catch blocks wherever it makes sense to catch and handle an exception (note that this means that you should not have try..catch blocks in all methods)
So, where does it make sense to catch and handle an exception? In short, where your code has knowledge that makes it capable of handling the exception. If it does not, let the exception bubble upwards to the caller. The only place where I think you should catch all exceptions and have some generic default behavior around what to do, it at the top level of your app. That is typically the UI.
Sorry, this is not a good idea. When you catch an exception in your code with a normal try/catch block surrounding the relevant section, you get to use two critical pieces of information to deal with the problem: the type of exception, and also where the exception occured.
With your arrangement, you have to deal with all exceptions knowing only what type of exceptions they are. You no longer know where the exception actually occured, so you really can't do anything about the problem other than to log it or show a message to the user.
Moreover, try/catch blocks often also include a finally block, in which you can make sure things happen even if an exception is thrown (like closing streams etc.). You don't have any way in your arrangement of dealing with this.
Proper exception handling can be tricky, and there is no magic bullet that will make it simple and straightforward. If there were, .Net would have already incorporated it.
We have a class in our code-base that has a pretty similar signature to the one you have proposed and I can tell you now that it has only bough misery and suffering!
Why do you have so many try-catch blocks in your code? Can you give some examples? Exceptions by their very nature "Exceptional", i.e.not that frequent! Not only should you not be catching exceptions that frequently, but also every exception is different and the same boilerplate code that works in one situation probably isn't suitable in many other situations.
Nobody said that exception handling was easy (or produced compact code) - you should think carefully about each situation you need to catch an exception and handle it appropriately - avoid catching exceptions that you don't need to handle.