One class I am writing implements IDictionary<string, object>
. In my CopyTo
implementation, I would like to use code contracts: stuff like Contract.Requires<ArgumentNullException>(array != null)
.
But, I get this warning (with some namespaces removed for readability):
Method 'LuaDictionary.CopyTo(KeyValuePair<String,Object>[],Int32)
' implements interface method 'ICollection<KeyValuePair<String,Object>>.CopyTo(KeyValuePair<String,Object>[],Int32)
', thus cannot add Requires
.
I see that there are some related questions, but they all seem to have to do with interfaces that are under the user's control. Obviously, IDictionary<T, U>
is not under my control, so I can't annotate it with ContractClassFor
or anything like that.
So am I just unable to use code contracts here? If so... major bummer...
Code Contracts provide a language-agnostic way to express coding assumptions in . NET programs. The contracts take the form of preconditions, postconditions, and object invariants. Contracts act as checked documentation of your external and internal APIs.
Code contracts provide a way to specify preconditions, postconditions, and object invariants in . NET Framework code. Preconditions are requirements that must be met when entering a method or property.
It is a bummer, but is understandable because client code that uses instances of your class as IDictionary<string, object>
should not have to meet preconditions that are not expected of IDictionary<string, object>
.
You can read the answer provided to this SO question, which links to and quotes the Code Contracts User Manual, and you can look at this article, which explains the situation this way, and goes on to provide a simple example:
Note that the Liskov's substitution principle holds true for Code Contracts in much the same way it holds for plain classes. The Liskov's principles says the following:
Subclasses should always be substitutable for their base classes.
In terms of the Code Contracts API this means that a derived class (or a class that implements a contract-based interface) should not expect more preconditions as the parent.
Keep in mind that IDictionary<K,V>
already has that Requires
:)
You can view the existing contracts DLLs for classes under: C:\Program Files (x86)\Microsoft\Contracts
.
If you open mscorlib.Contracts.dll
using Reflector you can view the contracts for the collection classes; CopyTo
has the following:
public void CopyTo(T[] array, int arrayIndex)
{
Contract.Requires((bool)(array != null), null, "array != null");
Contract.Requires((bool)(arrayIndex >= 0), null, "arrayIndex >= 0");
Contract.Requires((bool)((arrayIndex + this.Count) <= array.Length), null, "arrayIndex + this.Count <= array.Length");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With