C#: 是否需要使用#pragma warning restore?

60

我从msdn得到以下信息:

#pragma warning disable warning-list
#pragma warning restore warning-list
在这些示例中,同时使用了disablerestore。如果我想要在整个文件中禁用它,是否有必要进行restore
如果我不进行restore,它会延续多久?警告会被禁用在编译后的所有内容中吗?还是仅仅禁用该文件其余部分?或者是被忽略了?
3个回答

63

如果您不还原,禁用状态将在文件其余部分保持活动。

有趣的是,这种行为并未语言规范中定义。 (见第9.5.8节) 但是,关于条件编译符号的9.5.1节确实指出了这种“直到文件结束的行为”

该符号仍然被定义,直到处理该同一符号的#undef指令,或者达到源文件的末尾。

由于'预处理器'实际上是编译的词法分析阶段的一部分,因此很可能这种行为是微软和所有其他实现的有效协议(尤其是因为替代方案将基于源文件编译顺序非常复杂和不确定)。


7
总结一下:行为未定义,因此我们需要恢复。 - Julian
“源文件结束”假设不适用于跨多个文件拆分的部分类... - McGuireV10
@McGuireV10 你的意思是#pragma会对其他文件中的部分类有效,还是无效? - StackOverthrow
2
@TKK,这似乎是“未定义的”,因为它取决于编译器处理文件的顺序。它会在编译器遇到它时生效,并保持生效状态直到明确禁用。文件末尾不适用于部分文件。您肯定希望在每个文件中需要时禁用和重新启用它。 - McGuireV10
“language specification”的链接已经过时。 - Pang

3
不,你会发现编译器一旦完成解析源文件,就会自动恢复任何已禁用的警告。
#pragma warning disable 649
struct MyInteropThing
{
    int a;
    int b;
}
#pragma warning restore 649

在上面的例子中,我已经关闭了警告CS00649,因为我打算以不安全的方式使用这个结构体。编译器将无法意识到我将要写入具有这种布局的内存,因此我希望忽略警告:

字段'field'从未被分配,并且始终具有其默认值'value'

但我不想让整个文件都不受检查。


如果警告已经被命令行参数禁用了怎么办?你最终会恢复你不应该恢复的内容。 - drowa
@drowa 那么我想你一开始就不需要禁用它。据我所知,C#编译器中没有与C++ push/pop相当的东西。因此,它并不会变得更好。 - John Leidegren

3
假设我有一个私有字段,使用反射进行初始化,编译器显然找不到任何直接写入该字段的代码,因此它会显示一个警告 - 我不想显示这个警告。
假设我还定义了另一个私有字段,在第一个字段下面3行,我忘记初始化,如果我禁用整个文件的警告,这将不会触发警告。
因此,#pragma warning 的最佳用法是在导致我想要抑制的警告的行之前放置“warning disable”,并在该行之后放置“warning restore”,以便文件中不同位置的相同条件仍会触发警告。

2
你提供了一个用例,并得出结论所有其他用例都是相同的。此外,我认为这应该是一条评论,而不是答案。 - Micha Wiedenmann
1
@MichaWiedenmann - 我试图通过例子来解释,我本可以写道“有时候你会在同一个文件中收到两个相同类型的警告,其中第一个是误报,但第二个是真正的错误”- 这样回答是否更好?在我看来,不是的,人们可能会声称没有真实世界的用例(如果他们没有在“误报”处停止阅读)。 - Nir

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