我正在编写一个(非常小的)框架来检查方法的前置条件和后置条件。入口点是(它们很容易成为方法;没关系):
public static class Ensures {
    public static Validation That {
        get { ... }
    }
}
public static class Requires {
    public static Validation That {
        get { ... }
    }
}
显然,当方法没有问题时,检查后置条件可能会很昂贵,而且实际上并不是必需的。所以我想要一个像这样工作的方法:
public static class Ensures {
    [ConditionalCallingCode("DEBUG")]
    public static Validation ThatDuringDebug {
        get { ... }
    }
}
whereConditionalCallingCodeAttribute意味着这个方法应该只在调用代码用定义的 DEBUG 符号编译时运行。这可能吗?
我希望客户端代码如下所示:
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;
    }
}
当然,我可以不提供WhileDebuggingThat。然后客户端代码将如下所示:
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;
    }
}
如果没有其他办法,这是后备计划,但它非常严重地破坏了 DRY。
据我了解,标记WhileDebuggingThatwith[Conditional("DEBUG")]将发出(或不发出)此方法,具体取决于在库编译期间是否定义了 DEBUG,而不是引用该库的程序集。所以我可以这样做,然后编写文档告诉库用户将其代码的调试版本与库的调试版本链接起来,并将发布版本与发布版本联系起来。这对我来说并不是最好的解决方案。
最后,我可以告诉图书馆用户在他们的项目中定义这个类:
using ValidationLibrary;
public static class EnsuresWhileDebugging {
    [Conditional("DEBUG")]
    public static Validation That() {
        return Ensures.That;
    }
}
据我所知,这应该也可以,但仍然需要打破 DRY 原则,即使只是轻微的。