Given that we aren't supposed to be catching Contract failures, and since there isn't an overload for Contract.Invariant with an explicit specified exception, this answer is hopefully hypothetical.
So after all the disclaimers, you could hack something along the following lines, by wiring up a ContractFailed event handler:
Contract.ContractFailed += Contract_ContractFailed();
And in the handler, filter for Invariant
failures, and handle the failure and re-throw your exception:
public static void Contract_ContractFailed(object sender, ContractFailedEventArgs e)
{
if (e.FailureKind == ContractFailureKind.Invariant)
{
e.SetHandled();
throw new E(e.Message, e.OriginalException);
}
}
Given that you can't pass much information in the Contract.Invariant
definition, if you needed to parameterize the thrown exception, you would need to encode the intended exception into e.g. the bool, string
Contract.Invariant
overload, or use external global state, such as thread local storage.
All of these are smelly IMO. So to answer your last question, I believe throwing catchable exceptions isn't a good idea at all - your code is being called out of its designed range of state, so there is a bug / validation missing somewhere.
Edit
Noticed subsequently that handling + throwing in the ContractFailed
handler is still wrapped in the internal ContractException
. So you'll need to unpack, e.g.
catch(Exception ex)
{
var myException = ex.InnerException;
// ... do something
}