Note: this is not a duplicate of Jeff's question.
That question asked "Is an equivalent?" I know there isn't, and I want to know why!
The reason I ask is that I've only just become clear on how important it is, and the conclusion seems very strange to me.
The Exception Handling block of Microsoft's Enterprise Library advises us to use this pattern:
catch (Exception x)
{
if (ExceptionPolicy.HandleException(x, ExceptionPolicies.MyPolicy))
throw;
// recover from x somehow
}
The policy is defined in an XML file, so that means that if a customer has an issue, we can modify the policy to assist with tracking down (or perhaps papering over) the problem to give them a fast resolution until we deal with it properly - which may involve arguing with 3rd parties, about whose fault it all is.
This is basically an acknowledgement of the simple fact that in real applications the number of exception types and their "recoverability" status is practically impossible to manage without a facility like this.
Meanwhile, the CLR team at MS says this is not an option, and it turns out those guys know what they're talking about! The problem is that right before the catch
block runs, any finally
blocks nested inside the try
block will be executed. So those finally
blocks may do any of the following:
- Harmlessly modify the program state (phew, lucky).
- Trash something important in the customer's data, because the program state is screwed up to an unknown degree.
- Disguise or destroy important evidence that we need to diagnose an issue - especially if we're talking about calls into native code.
- Throw another exception, adding to the general confusion and misery.
Note that the using
statement and C++/CLI destructors are built on try
/finally
, so they're affected too.
So clearly the catch
/throw
pattern for filtering exceptions is no good. What is actually needed is a way to filter exceptions, via a policy, without actually catching them and so triggering the execution of finally
blocks, unless we find a policy that tells us the exception is safe to recover from.
The CLR team blogged about this recently:
The outcome is that we have to write a helper function in VB.NET to allow us to access this vital capability from C#. The big clue that there is a problem is that there is code in the BCL that does this. Lots of people have blogged about doing it, but they rarely if ever mention the thing about try
/finally
blocks, which is the killer.
What I would like to know is:
- Are there any public statements or direct emails people have received from the C# team on this subject?
- Are there any existing Microsoft Connect suggestions asking for this? I've heard rumours of them but none of the likely keywords turned up anything.
Update: as noted above, I have already searched on Microsoft Connect without finding anything. I have also (unsurprisingly) Googled. I've only found people explaining why they need this feature, or pointing out the advantages of it in VB.NET, or fruitlessly hoping that it will be added in a future version of C#, or working around it, And plenty of misleading advice. But no statement on the rationale for omitting it from all current versions of C#. And the reason I'm asking about existing Connect issues is so that (a) I don't create an unnecessary duplicate and (b) I can tell interested people if I have to create one.
Update 2: Found an interesting old blog post from Eric Gunnerson, formerly of the C# team:
"Yes, being able to put a condition on
a catch is somewhat more convenient
than having to write the test
yourself, but it doesn't really enable
you to do anything new."
That was the same assumption I had until it was properly explained to me!
See Question&Answers more detail:
os