In writing some code to mimic an as-complete-as-possible emulation of System.Array, I have come across something that I find confusing and dangerous.
With the following method signature:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static int BinarySearch<T>(T[] array, T value, IComparer<T> comparer)
A method is declared with a contract saying that it will definitely not corrupt any state, even itself, if there is a failure. It also implies that some code external to the contract will be called via the comparer
value, and IComparer<T>.Compare
does not require a reliability contract; a call to comparer.Compare(x,y)
can certainly corrupt state and violate the contract.
How is this valid? I'm not an expert on the uses of constrained execution... will a constrained execution environment inspect the Compare
method at runtime, and cause an exception if the contract is expected to be enforced? Is this a hole in the reliability contract?
Or, are constrained execution regions CIL voodoo that I should avoid in non-framework code? I want to keep as close as possible behavior to native System.Array, and so I would like to maintain the same ReliabilityContract
attributes where the underlying implementation supports it; but it seems to me that even the internals can't guarantee the contract, so I am quite puzzled how I could guarantee the contract.
AFAIK, CERs are a very advanced feature and are used very rarely. Unless you really want your class to be usable in a CER (or if you're not sure what CERs actually are), you shouldn't specify any
ReliabilityContract
.If you still want to investigate CERs, read Stephen Toub's Keep Your Code Running with the Reliability Features of the .NET Framework. I think the most relevant part of that article is (emphasis mine):
I think the highlighted section means that
BinarySearch
shouldn't have been marked asWillNotCorruptState
. Or it's possible that the case with a delegate is more transparent than callingEquals()
of a passed inobject
, so the attribute is actually okay here.In any case, I think that to be on the safe side, you shouldn't specify any
ReliabilityContract
s, unless you really know what you're doing and you really need it.