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

时间:2009-12-18 21:27:53

标签: c# compiler-warnings

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

const bool ExecuteThis=true;
const bool ExecuteThat=false;

然后使用它的代码

if(ExecuteThis){ DoThis(); }
if(ExecuteThat){ DoThat(); } //unreachable code warning here

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

8 个答案:

答案 0 :(得分:55)

要禁用:

#pragma warning disable 0162

要恢复:

#pragma warning restore 0162

有关#pragma warning的更多信息,请参阅MSDN

请注意,C#编译器已经过优化,不会发出无法访问的代码。这称为dead code elimination,它是few optimizations that the C# compiler performs之一。

你不应该毫不犹豫地禁用这些警告。警告是问题的症状。请参阅此answer

答案 1 :(得分:25)

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

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

然而,然而,由编译器检查。仅此一点可能就是无视我的咆哮的理由。

换句话说,摆脱警告的净效果只是,你摆脱警告。

另请注意,此答案是意见。您可能不同意我的观点,并希望使用#pragma来屏蔽警告消息,但至少对此有什么了解。如果你这样做,谁在乎我的想法。

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

您使用的是consts而不是“define”吗?

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

为什么代码甚至存在?它将从不执行。

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

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

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

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

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

要完成这个答案,我想知道你的问题是否完全不同。

通常,当我看到代码中包含“检测到无法访问的代码”的警告时,它们会属于以下类别之一:

  1. 错误(在我看来)使用const与编译器#define,你基本上对编译器说:“这段代码,请编译它,即使我知道它也会不得使用。“。
  2. 错误,就像在一般情况下一样,只是一个开关盒,它有一个包含throw + a break的case-block。
  3. 以前迭代中的剩余代码,您只是通过在某个时刻添加返回来缩短方法,而不是删除(或者甚至注释掉)后面的代码。
  4. 取决于某些配置设置的代码(即仅在Debug-builds期间有效)。
  5. 如果您拥有的代码不属于上述任何设置,您的常量将更改的具体情况?知道这可能会给我们更好的方法来回答你如何处理它的问题。

答案 2 :(得分:22)

如何使用预处理程序语句呢?

#if ExecuteThis
    DoThis();
#endif

#if ExecuteThat
    DoThat();
#endif

答案 3 :(得分:11)

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

[Conditional("SOME_KEY")]
void DoThis() {...}
[Conditional("SOME_OTHER_KEY")]
void DoThis() {...}

现在只有在DoThisDoThat被定义为构建中的符号时才会包含调用SOME_KEY / SOME_OTHER_KEY(“条件编译符号“)。它还意味着您可以通过更改配置并在每个配置中定义不同的符号来切换它们。

答案 4 :(得分:3)

您在代码中声明了常量这一事实告诉我,您正在使用每个版本重新编译代码,而不是使用来自配置文件的“内容”。

所以解决方案很简单:   - 从存储在配置文件中的值设置“常量”(标志)   - 使用条件编译来控制编译的内容,如下所示:

#define ExecuteThis
//#define ExecuteThat

public void myFunction() {
#if ExecuteThis
    DoThis();
#endif
#if ExecuteThat
    DoThat();
#endif
}

然后,当您重新编译时,只需取消注释正确的#define语句即可编译正确的代码。有一两种方法来声明条件编译标志,但这只是给你一个例子,并在某处开始。

答案 5 :(得分:3)

在不修改代码的情况下“摆脱它”的最快方法是使用

#pragma warning disable 0162

在您想要压制警告的名称空间,类或方法上。

例如,这不会再发出警告了:

#pragma warning disable 0162
namespace ConsoleApplication4
{
  public class Program
  {
    public const bool something = false;

    static void Main(string[] args)
    {
        if (something) { Console.WriteLine(" Not something" ); }

    } 
 }

但是请注意,此命名空间中的NO METHOD将再次发出警告......而且..警告是有原因的(如果它没有计划无法到达时会发生什么?)

我想更安全的方法是在配置文件中编写变量,并在程序开头从那里读取它们,这样你甚至不需要重新编译就可以了你的不同版本/发布!只需更改应用程序文件即可:D。

关于速度惩罚..是的..按照这种方式进行查询会有速度惩罚...与使用const相比,但除非你真的担心要多跑1/100毫秒......我会这样做。

答案 6 :(得分:3)

这是一个绝招:

    bool FALSE = false;
    if (FALSE) { ... 

这将阻止警告。等待。我知道所有这些"你不应该使用它,为什么代码没有被执行?"。答:因为在开发过程中,您经常需要设置测试代码。最终你会摆脱它。在开发过程中代码存在是非常重要的,但不是一直执行。

有时您想暂时删除代码执行,以进行调试。

有时您希望暂时截断函数的执行。您可以使用它来避免警告:

...代码..          {bool TRUE = true; if(TRUE)返回; }    ...更多代码...

这些事情避免了警告。你可能会说,如果是暂时的,应该保留警告。是的......但是......但是也许你不应该以这种方式检查它,但是暂时将警告输出是有用的,例如当你花一整天时间调试复杂的碰撞代码。

所以,你可能会问,为什么这很重要?好吧,当我按F4转到第一个错误时,这些警告变得非常烦人,并且首先得到一些该死的10个警告而且我在调试时膝盖很深。

使用#pragma,你说。嗯,这是一个好主意,除了我无法找到一种方法在我的整个项目中全局地做到这一点..或者以一种可以与Unity3D一起使用的方式,这就是我用C#编写的代码。哦,#include会有多大用处。

没关系,请使用#if!嗯......是的......但有时它们不是你想要的。它们使代码变得混乱且难以理解。你必须用恰当的方法将代码括起来。将if(假)放在块前面就更容易了......不需要划分块,大括号就是这样。

我所做的是做一个很好的全局可访问的FALSE和TRUE并使用它们,因为我需要避免错误。

如果我想检查一下我是否真正使用它们,我可以搜索所有引用,或者更粗略地搜索所有引用,但同样有效,删除它们,从而被迫查看这个小技巧的每一个出现。

答案 7 :(得分:2)

最简单的方法是停止编写无法访问的代码:D #DontDoThat