I've been thinking about how to add pre- and post- condition checks to (C#) functions.
Roughly, preconditions are conditions that should be true at the start of a function, and post conditions should be true at the function exit. e.g.:
/**
* Return x divided by y
*/
public int Divide(int x, int y) { ... }
has a precondition that y
should not be zero.
It's easy to add these kinds of checks to a function:
public int Divide(int x, int y) {
if (y == 0) {
throw new ArgumentException("y must not be zero");
}
...
but a) they're not obviously condition checks and b) it might be nice to be able to turn them off in Release mode. (Potentially also c) they could be extracted for a test suite)
I've been thinking in terms of Attributes, but C# doesn't support Lambdas in Attributes, and probably won't any time soon. However, a new idea arrived today:
public int Divide(int x, int y) {
Contract.Pre(y, q => q != 0, "y must not be zero");
...
With a definition something like
[StackTraceHidden]
[Conditional("Development")
public void Pre<TParam>(TParam value, Func<TParam, bool> test, string onFailMessage) {
if (!test(value)) {
throw new ArgumentException(onFailMessage);
}
}
it would transparently (i.e., not showing in a stack trace) run the test in development mode, and not even be included as a call in Release.
I imagine that it would be worth adding some overrides (or sibilings) for common cases, such as Contract.PreIsNotNull
, Contract.IsOfType
. (Alternativly, include a bunch of predicates in the library).