我正在编写一个(非常小的)框架来检查方法的前置条件和后置条件。入口点是(它们很容易成为方法;这无关紧要):
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 { ... }
}
}
其中 ConditionalCallingCodeAttribute
表示此方法应仅在使用定义的 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。
据我了解,用 [Conditional("DEBUG")]
标记 WhileDebuggingThat
将发出(或不发出)此方法,具体取决于在编译期间是否定义了 DEBUG库的,不是引用该库的程序集。所以我可以这样做,然后编写文档告诉库用户将他们代码的调试版本与库的调试版本链接起来,并将发布版本与发布版本链接起来。这并不是我认为的最佳解决方案。
最后,我可以告诉库用户在他们的项目中定义这个类:
using ValidationLibrary;
public static class EnsuresWhileDebugging {
[Conditional("DEBUG")]
public static Validation That() {
return Ensures.That;
}
}
据我所知,这也应该有效,但仍然需要打破 DRY 原则,即使只是轻微的。
最佳答案
这是正常的ConditionalAttribute吗?除了处理属性而不是方法之外,对您没有帮助吗?您可能需要更改调用方式,以便获得方法而不是属性 - 而它返回值的事实可能会导致问题。
如果您能展示您的框架是如何使用的,那将会很有帮助——目前我们没有太多可以使用的。
另一件需要考虑的事情是提供库的各种二进制构建 - 这样调用者就可以提供一个实际上不做任何检查的不同版本。不过,仅凭您提供的代码很难判断。
关于c# - 在 .Net 中是否可以仅从客户端程序集的调试版本中调用某些代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/394921/