【发布时间】:2014-05-10 19:53:53
【问题描述】:
在经典 C 中,我可能有一个 1.0 版本的库,它在其 .h 文件中定义了一个常量,例如:
#define LIBRARY_API_VERSION_1_0
我可以在我的应用程序代码中做这样的事情:
#include "LibraryApi.h"
// ...
int success;
#ifdef LIBRARY_API_VERSION_1_0
int param = 42;
success = UseThisMethodSignature(42);
#endif
#ifdef LIBRARY_API_VERSION_2_0
float param = 42.0f;
success = UseOtherMethodSignature(param);
#endif
现在我正在使用 C#。因此,显然#defines 仅适用于定义它们的文件,因此我研究了使用带有常量的静态类的解决方案described here。但是,该解决方案需要在运行时进行检查,这会带来许多问题:
- 如果我一遍又一遍地运行相同的代码并检查额外的条件,可能会效率低下(尽管如果它是
const,也许编译器或 .NET 运行时足够聪明,可以避免这种情况?) - 您不能做会引发编译器错误的事情。在我上面的例子中,我用两种不同的类型定义了两次
param。此外,UseOtherMethodSignature可能不作为函数存在,如果两个块仅由if/else分隔,则无法编译。
那么,对于这类问题,公认的解决方案是什么?我的场景是我有多个版本的 Web 服务 API(根据您使用它的方式而有不同程度的差异),并且我希望能够在不注释/取消注释一堆代码或其他代码的情况下进行编译同样愚蠢的手动过程。
编辑
对于它的价值,我更喜欢编译时解决方案——在我的场景中,我知道当我编译要使用哪个版本时,我不需要弄清楚库的哪个版本在运行时在系统上可用。是的,这行得通,但似乎有点矫枉过正。
【问题讨论】:
-
如果您使用 API 的 v1 构建,但在执行时只存在 v2,您会发生什么?请记住,虽然
#define本身仅适用于源文件级别,但您可以指定与项目属性相同的标记。 -
@JonSkeet 好问题,我想它会崩溃。我认为这正是发生的情况,例如,您从 C 代码构建二进制文件并动态链接它,但在没有该库/版本的系统上运行它。但在我的场景中,这是一个我有源代码的库,我将它编译成一个可部署的 ASP.NET 应用程序,所以这不是一个问题。在这种情况下,它更像是静态链接。