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();
}
}
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.
https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/clr-abi.md#general-unwindframe-layout
The catch block isn't needed and neither is the try block: if they're trying to guarantee cleanup they could just use a
usingstatement as that will work even if there is an exception.