有没有办法让VS2008停止警告我无法访问的代码?

Ear*_*rlz 32 c# compiler-warnings

我的应用程序中有一些配置选项

const bool ExecuteThis=true;
const bool ExecuteThat=false;
Run Code Online (Sandbox Code Playgroud)

然后像使用它的代码

if(ExecuteThis){ DoThis(); }
if(ExecuteThat){ DoThat(); } //unreachable code warning here
Run Code Online (Sandbox Code Playgroud)

问题是,我们可能会制作略有不同的版本,而不是ExecuteThis或ExecuteThat,我们希望能够使用consts,这样我们就不会在运行时对这些事情进行任何速度惩罚.但我厌倦了看到关于无法访问的代码的警告.我是一个喜欢消除所有警告的人,但我对这些事情无能为力.我可以使用一些选项来关闭这些警告吗?

jas*_*son 55

要禁用:

#pragma warning disable 0162
Run Code Online (Sandbox Code Playgroud)

恢复:

#pragma warning restore 0162
Run Code Online (Sandbox Code Playgroud)

有关详细信息#pragma warning,请参阅MSDN.

请注意,C#编译器已经过优化,不会发出无法访问的代码.这称为死代码消除,它是C#编译器执行少数优化之一.

而你不应该无所事事地禁用警告.警告是问题的症状.请看这个答案.

  • 请务必阅读Lasse V. Karlsen(http://stackoverflow.com/users/267/lasse-v-karlsen)的答案(http://stackoverflow.com/questions/1930793/is-there-a-way-对获得-VS2008到停止警告-ME-约不可达代码/ 1930840#1930840).我所做的只是告诉你如何做你想做的事.他的回答告诉你为什么你应该首先避免陷入这种情况. (4认同)

ang*_*son 24

首先,我同意你的意见,你需要摆脱所有的警告.你得到的每一个小警告,通过解决问题摆脱它.

在继续阅读之前,重新阅读的内容相当于咆哮,让我强调使用这样的代码似乎没有任何性能损失.使用Reflector检查代码后,看起来被"标记"为无法访问的代码实际上并未放入输出程序集中.

但是,它由编译器检查.仅凭这一点可能是我无视我的咆哮的充分理由.

换句话说,摆脱那个警告的净效果只是,你摆脱了警告.

另请注意,这个答案是一个意见.您可能不同意我的意见,并希望用来#pragma掩盖警告信息,但至少对这是做什么有明智的意见.如果你这样做,谁在乎我的想法.

话虽如此,为什么要编写无法访问的代码?

你使用的是consts而不是"define"吗?

警告不是错误.对你来说,分析这段代码并弄清楚你是否做对了.通常,你没有.对于您的特定示例,您有意编译代码,对于您的特定配置,该代码永远不会执行.

为什么代码甚至存在?它永远不会执行.

您是否对"常数"这个词实际意味着什么感到困惑?一个常数意味着"这永远不会改变,如果你认为它会,它不会是一个常数".这就是常数.它不会,也不会,也不应该改变.永远.

编译器知道这一点,并告诉你你有代码,由于常量,永远不会执行.这通常是一个错误.

这种情况会不会改变?如果是,它显然不是常量,而是取决于输出类型(Debug,Release),它是"#define"类型的东西,所以删除它,然后使用该机制.这使得阅读代码的人更清楚这个特定代码所依赖的内容.如果您选择了未设置定义的输出模式,Visual Studio也将有助于使代码变灰,因此代码将无法编译.这就是编译器定义要处理的内容.

另一方面,如果常量不会改变,无论出于何种原因,删除代码,您都不会需要它.

在任何情况下,不要成为简单的解决方案的牺牲品,只是禁用该代码的警告,这就像服用阿司匹林"修复"你的背部疼痛问题.这是一个短期的解决方案,但它掩盖了这个问题.而是修复潜在的问题.

为了完成这个答案,我想知道你的问题是否没有完全不同的解决方案.

通常,当我看到具有"检测到无法访问的代码"警告的代码时,它们属于以下类别之一:

  1. 错误(在我看来)const与编译器的使用#define,你基本上对编译器说:"这段代码,请编译它,即使我知道它不会被使用."
  2. 错误,就像在一般情况下一样,就像一个开关盒一样,它有一个包含throw + a break的case-block.
  3. 以前迭代中的剩余代码,您只是通过在某个时刻添加返回来缩短方法,而不是删除(或甚至注释掉)后面的代码.
  4. 代码取决于某些配置设置(即仅在Debug-builds期间有效).

如果您拥有的代码不属于上述任何设置,那么您的常量会发生变化的具体情况是什么?知道这可能会给我们更好的方法来回答你如何处理它的问题.

  • "然而,这是由编译器检查的.仅凭这一点可能是一个不足以忽视我的咆哮的理由." - 我会说这是我无视它的原因...我讨厌有一些可能编译或不编译的配置..我喜欢没有警告的代码(如同,我解决所有问题)但我知道原因警告真的没什么大不了的......(而且,这不像是我禁用整个项目的警告) (4认同)
  • @Offler 不,那是不正确的,它不会那样做。如果您为 DEBUG 编译它,因此包括返回,那么是的,该方法的其余部分将为您提供无法访问的警告。但是,如果您为 RELEASE 编译它,其中不包括返回,您将不会收到警告。编译器在这两种情况下都是正确的。 (2认同)
  • 当我理解您的意思时,我觉得C#中的#define语法还有很多不足之处。例如,像#if MYCONSTENT这样的错字最终将总是为false,而不是像if(MyConstent)这样的编译器错误,它会更安全。另外,如果您后来删除了const,则可以将其删除,然后修复错误,而使用#define const则必须使用Ctrl + F,如果您错过了const, “ #if”将始终为假。同样,`#define`常量始终在文件范围内,并且没有`#include`像C / C ++中那样。 (2认同)

Jas*_*own 22

那么使用预处理器语句呢?

#if ExecuteThis
    DoThis();
#endif

#if ExecuteThat
    DoThat();
#endif
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这种方法,但我重视这样一个事实:无论预处理器指令是什么,我的代码都必须始终编译。 (2认同)
  • 预处理器语句肯定是在编译时设置标志的方式,并且将确保不会编译"无法访问的代码",比const bool安全得多.另外,除了"Debug"和"Release"之外,您还可以进行额外的配置,这些配置将插入这些定义,例如"Debug ExecuteThis". (2认同)
  • 请注意,使用"if(x){...}",其中x被定义为`const Boolean x = false;`实际上不会将代码放入程序集中.警告是告诉你刚刚发生的,这可能是一个问题. (2认同)

Mar*_*ell 11

嗯,#pragma但这是一个但又蹩脚的.我想知道是否ConditionalAttribute会更好 - 即

[Conditional("SOME_KEY")]
void DoThis() {...}
[Conditional("SOME_OTHER_KEY")]
void DoThis() {...}
Run Code Online (Sandbox Code Playgroud)

现在要求DoThis/ DoThat如果只包括SOME_KEYSOME_OTHER_KEY定义为在构建符号("条件编译符号").它还意味着您可以通过更改配置并在每个配置中定义不同的符号来在它们之间切换.