I am writing a (very small) framework for checking pre- and postconditions of methods. Entry points are (they could be easily be methods; that doesn't matter):
public static class Ensures {
public static Validation That {
get { ... }
}
}
public static class Requires {
public static Validation That {
get { ... }
}
}
Obviously, checking the postconditions may be expensive, and isn't actually necessary, when the method isn't buggy. So I want a method which works like this:
public static class Ensures {
[ConditionalCallingCode("DEBUG")]
public static Validation ThatDuringDebug {
get { ... }
}
}
where ConditionalCallingCodeAttribute
means that this method should only run when the calling code is compiled with the DEBUG symbol defined. Is this possible?
I want client code to look like this:
public class Foo {
public void Bar() {
... // do some work
Ensures.That // do these checks always
.IsNotNull(result)
.IsInRange(result, 0, 100);
Ensures.WhileDebuggingThat // only do these checks in debug mode
.IsPositive(ExpensiveCalculation(result));
return result;
}
}
Of course, I can simply not provide WhileDebuggingThat. Then the client code would look like this:
public class Foo {
public void Bar() {
... // do some work
Ensures.That // do these checks always
.IsNotNull(result)
.IsInRange(result, 0, 100);
#ifdef DEBUG
Ensures.That // only do these checks in debug mode
.IsPositive(ExpensiveCalculation(result));
#endif
return result;
}
}
This is the fallback plan if nothing else works out, but it breaks DRY really badly.
As I understand it, marking WhileDebuggingThat
with [Conditional("DEBUG")]
will emit (or not) this method depending on whether DEBUG is defined during the compilation of the library, not of the assemblies which reference this library. So I could do this and then write documentation telling the library users to link debug builds of their code with the debug build of the library, and release builds with release builds. This doesn't strike me as the best solution.
Finally, I could tell the library users to define this class inside their projects:
using ValidationLibrary;
public static class EnsuresWhileDebugging {
[Conditional("DEBUG")]
public static Validation That() {
return Ensures.That;
}
}
This should work as well, as far as I see, but still requires breaking the DRY principle, if only slightly.