C#代码是否可以根据编译器(或语言)版本进行条件编译?

4
我想知道是否可以根据编译器版本对任意的C#代码进行条件控制。特别地,我想在MSVS 2010 C#编译器中禁止已知不会由2013编译器产生的Code Analysis警告; 我希望这样做是逐个案例进行的,因此可能是在源代码中实现。

相关问题

一个示例问题

虽然我对这个问题很感兴趣,但我真正想要的是一个通用的答案。

MSVS 2010会在字符串文字中给出CA2204(“更正拼写…”)警告,而2013则让我通过Custom Dictionary中的<Compound>元素消除了这个警告。2010的文档建议它只支持元素<Dictionary> — <Words> — <Recognized> — <Word>(但似乎没有问题使用包括<Compound>的字典)。

我部分使用MSVS 2013进行编程和测试(其中各种检查更好),部分使用2010(它位于我们最佳测试服务器上)。我有两个编译器的项目定义。理想情况下,我希望2010能及时检测到问题,而不是等到我用2013编译后再检测,所以我想尽可能少地进行抑制,而不是在项目中全面抑制CA2204。

因此,我考虑在类似#if !MSVS2013的条件下包含一个[CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204…"…]属性,但似乎没有可行的功能测试。

可能的解决方案

按不满意程度递减的顺序,我考虑了以下内容,并且很想听听别人认为哪个最好:

  • (我没有发现的)简单可靠的东西。 这就是我所希望的!
  • 在MSVS项目中抑制CA2204。 容易但全面。
  • 在MSVS项目中手动定义宏MSVS2013,适用于至少该级别的任何编译器,并像上面那样抑制。 有点尴尬,但可行。
  • 在MSVS项目中自动派生宏,可能使用this answer中提到的Microsoft.Build.Tasks.Csc.LangVersion听起来很强大,但设置起来很棘手,我还没有进一步调查。
  • 将我们的测试服务器升级到MSVS 2013。 如果可以接受,可能是明智的选择-但不能回答这个问题!
  • 我认为不行:
    • 在2010年中创建一个子类class SuppressMSVS2010MessageAttribute : SuppressMessageAttribute,在2013年中是虚拟的。 [SuppressMessage]sealed
    • 使用条件属性(语言规范3.0 §17.4.2.2) 条件性是属性类的属性,而不是属性实例的属性!我没有继续跟进,因为我认为这没有帮助。

1
很难理解为什么 [CodeAnalysis.SuppressMessage] 属性需要有条件。 - Hans Passant
@HansPassant:我并不是说它_需要_是有条件的,只是听起来像是可能会给予所需的灵活性。_只是头脑风暴_。 - PJTraill
当你有一个真正的例子时,欢迎回来,SO的大门永远敞开着。 - Hans Passant
@HansPassant:我认为我找不到一个有条件属性的相关示例,因为我认为它们不是解决方案;我只是想提出一些解决方案的想法供人们评论;毕竟,解释为什么某些方法不起作用可能非常有帮助。我想这就是我所说的“只是头脑风暴”。 - PJTraill
@HansPassant:实际上,SuppressMessage是有条件的,但只在CODE_ANALYSIS上,类的文档中说:“ConditionalAttribute应用于此类,指定预处理符号“CODE_ANALYSIS”作为条件符号,确定是否包括或省略属性调用。如果定义了该符号,则包括属性调用;否则,调用将被省略。” …当然,这并没有什么帮助。 - PJTraill
1个回答

4

请问C#代码能否根据编译器(或语言)版本进行条件判断?

可以。如果您根据正在使用的编译器版本手动定义符号,则可以。否则,不行。

从文档中得知

C#编译器本身没有定义您可以在源代码中使用的符号或宏;所有符号定义都必须是用户定义的。

也就是说,“没有符号”也包括没有预定义的符号,使您无法确定编译器版本并因此有条件地控制编译。


注意:自然而然,“手动定义”并不排除您撰写自己的构建过程,在其中包括检查程序以确定其版本,然后定义您用于控制编译的某些符号的构建步骤。就编译器本身而言,这仍然是“手动”的,但您可以自动化执行此过程。


1
感谢您找到了那个声明。我已经在语言定义中查找过了,但这当然实际上是一个编译器问题——不同的编译器可能会定义不同的东西。除非您将“_。 在源文件的词法处理开始时,条件编译符号未定义,除非它已被外部机制(如命令行编译器选项)显式定义。”(3.0和5.1版本的§2.5.1)解读为此,否则该语言似乎并未强制规定编译器不得定义任何内容,而我并不认为是这样的。 - PJTraill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接