C# 使用编译器指令支持多个平台
这是一个通用的软件设计问题 使用#if编译器指令支持多个平台是一个好主意吗。例如,我有三个文件: IScreen.csC# 使用编译器指令支持多个平台,c#,software-design,compiler-directives,C#,Software Design,Compiler Directives,这是一个通用的软件设计问题 使用#if编译器指令支持多个平台是一个好主意吗。例如,我有三个文件: IScreen.cs public interface IScreen { ... } ScreenWin.cs #if WIN public class Screen : IScreen { ... } #endif ScreenMac.cs #if WIN public class Screen : IScreen { ... } #endif 这似乎很酷,因为我可
public interface IScreen {
...
}
ScreenWin.cs
#if WIN
public class Screen : IScreen {
...
}
#endif
ScreenMac.cs
#if WIN
public class Screen : IScreen {
...
}
#endif
这似乎很酷,因为我可以使用BDD,并拥有如下功能:
Given a Screen exists with width: 1920 and height: 1080
并且将根据编译器指令使用正确的屏幕
这似乎也比尝试使用抽象工厂获得更好的性能
缺点是什么?缺点包括必须编译多个二进制文件-每个平台一个 如果不小心,您可能会在代码的许多部分使用预处理器指令将代码弄乱。请参阅有关反转这样一个代码库的问题
如果可以在代码中检测平台,这是一种更好的方法。正如@Oded所回答的,使用编译时directoves的缺点是必须为每个平台编译特定的二进制文件。好的一面是,你没有一个臃肿的一刀切的应用程序,它在每个平台上都更大、更慢,仅仅因为它是平台独立的
另一个下侧是如果很多VisualStudio工具只考虑“当前活动”代码。例如,intellisense和重构工具—如果您希望将IScreen重命名为IDisplay,那么您会发现重构工作正常,所有PC代码都得到了完美更新,但所有Mac代码都会严重损坏,因为重构工具根本看不到其他代码分支。类似地,很容易在PC分支上更改代码,而忘记对Mac分支进行相应的更改,从而再次破坏它
工厂而不是“#if”的好处是,单个二进制映像可能可以在每个平台上运行,并且在创建具体实现时只需检查主机平台一次(因此在运行时仍然非常有效,但会更大,因为您必须在一个发行版中发布所有平台变体)然而,通过使用更模块化的设计模式而不是#如果:将卫星组件用于特定于平台的实现,则可以实现两个方面的最佳效果。在这种方法中,主应用程序代码将指定
IScreen
接口,然后在ScreenImplementation.dll程序集的不同平台特定变体中有具体的Screen
(Mac)和Screen
(PC)类。您还可以发布一个覆盖所有平台的安装程序(只需为主机平台部署适当的卫星dll)。这使得使用#if的效率/大小得到了边际的提高,但实际上不必用条件来打乱代码。(当然,这种模块化方法对#if和工厂设计都有意义——一旦将特定于平台的实现拆分为单独的程序集,它们就更像是一种部署选项,而不是核心实现体系结构)管理编译器指令的可伸缩性非常差。我也是,谢谢你的回答。嗯。这个指令链接看起来很糟糕。我已经远离指令很久了。我第一次考虑使用它们,我会考虑单个二进制的优点。重构问题是一个很大的缺点。谢谢你指出这一点。二进制膨胀可能是个问题。我首先考虑这种方法的唯一原因是我们对所有编码都使用BDD。例如,我们可以在Mac上实现屏幕。签入Git。在Windows环境中签出,测试将失败。在windows上实现这些场景,现在两个系统的行为都相同了。在这两种环境中工作的团队也会很快发现系统行为的任何变化。谢谢你的回复。