Reputation: 30378
I found some code where they want to propagate an exception, but they want to run some clean-up code beforehand, so naturally it uses Try
/Catch
/Finally
. But... they aren't actually doing anything with the exception, only forwarding it on. It was my understanding in those cases the catch block isn't needed, but some say it actually is. I'm not sure those who do are correct.
Specifically, Microsoft's documentation on Try-Catch says the following...
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.
What does the computer have to do with it? With the exception (no pun intended) of using FailFast
, wouldn't a further-up try-catch block which called it properly catch this exception? And if that's what they mean, man that was an awkward way of saying it!
Still, I think it proves the catch{ throw; }
isn't needed, correct?
Consider the following code...
public static BitmapImage MakeBitmapImage(byte[] bytes){
var ms = new MemoryStream(bytes);
try{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
return bitmapImage;
}
catch{
throw;
}
finally{
ms.Close();
ms.Dispose();
}
}
Couldn't it just be re-written like this (with no catch
block) to propagate if the bitmap can't be loaded?
public static BitmapImage MakeBitmapImage(byte[] bytes){
var ms = new MemoryStream(bytes);
try{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
return bitmapImage;
}
finally{
ms.Close();
ms.Dispose();
}
}
Upvotes: 1
Views: 140
Reputation: 11110
I was going to say that this is a useless noop. But after reading your linked documentation in more detail that's not quite true.
There are some situations where the runtime may terminate your process without unwinding the thread stack and running any finally blocks. Perhaps if (and only if) there is no catch handler at all. Your program is going to crash anyway, or could crash due to processing in another thread, you probably don't care about that distinction.
In dotnet core, for some kinds of failures, the runtime may call Environment.FailFast and just crash immediately. Though I thought this was only for failures that didn't have any call stack, like an exception that occurs while restoring the execution context. And again, other threads probably won't be unwound.
But for any finally block that is disposing managed resources, this is absolutely pointless. I'd only worry about a finally block that performed other external operations, like a file rename. And then you're going to need to test what the actual behaviour is anyway.
Upvotes: 2
Reputation: 148
I am not fully sure what the author meant, but my educated guess is that "how your computer is set up." really means "how your architecture handles unwinding." This can be different in ARM and x86.
The catch block isn't needed and neither is the try block: if they're trying to guarantee cleanup they could just use a using
statement as that will work even if there is an exception.
Upvotes: 2