C#编译器应该发出警告但不是吗?

时间:2010-04-29 21:27:32

标签: c# compiler-construction warnings try-catch

我的团队中的某个人尝试在空的catch子句中修复“未使用的变量”警告。

try { ... } catch (Exception ex) { }

- >发出关于ex未被使用的警告。到目前为止,非常好。

修复是这样的:

try { ... } catch (Exception ex) { string s = ex.Message; }

看到这一点,我想“很棒,所以现在编译器会抱怨没有使用 s 。”

但事实并非如此!这条代码没有警告,我无法弄清楚原因。有什么想法吗?

PS。我知道将异常静音的全能条款是一件坏事,但这是一个不同的话题。我也知道通过做这样的事情可以更好地消除初始警告,这也不是重点。

try { ... } catch (Exception) { }

try { ... } catch { }

7 个答案:

答案 0 :(得分:25)

在这种情况下,编译器检测到s已写入但未读取,故意抑制警告。

原因是因为C#是一种垃圾收集语言,信不信由你。

你怎么想的?

好吧,请考虑以下事项。

你有一个程序调用一个返回字符串的方法DoIt()。您没有DoIt()的源代码,但是您希望在调试器中检查它的返回值是什么。

现在,在您的特定情况下,您使用DoIt()作为其副作用,而不是其返回值。所以你说

DoIt(); // discard the return value

现在你正在调试你的程序,然后你去查看DoIt()的返回值和它不在那里,因为调试器在调用DoIt()后中断时,垃圾收集器可能有已经清理了未使用的字符串

事实上,托管调试器没有“查看前一个方法调用返回的东西”的工具。非托管C ++调试器具有该功能,因为它可以查看丢弃的返回值仍然存在的EAX寄存器,但是您无法保证托管代码中的返回值在被丢弃时仍然有效。

现在,有人可能会认为这是一个有用的功能,并且调试器团队应该添加一个功能,如果在方法执行后立即出现调试器断点,则返回值保持活动状态。这将是一个很好的功能,但我是错误的人要求它;去询问调试组。

可怜的C#开发人员做什么?创建局部变量,将结果存储在局部变量中,然后在调试器中检查本地。调试器确实确保本地人不会积极地收集垃圾。

所以你这样做然后编译器会给你一个警告,你有一个只写入的本地,从不读,因为读取的东西不是程序的一部分,它是开发人员坐着在那里看着调试器。这是一个非常恼人的用户体验!因此,我们检测到非常量值被分配给局部变量或字段从未读取的情况,并禁止该警告。如果你更改了你的代码,而不是它string s = "hello";,那么你将开始收到警告,因为编译器的原因,嗯,这可能不是一个解决调试器限制的人,因为值是< em>就在那里开发人员可以在没有调试器的情况下读取它。

这解释了一个。在许多其他情况下,我们会禁止有关从未读取的变量的警告;一个detailed exegisis of all the compiler's policies当我们报告警告时,当我们不这样做会花费我相当长的时间来写,所以我想我会留下它。

答案 1 :(得分:9)

使用变量s来保存对ex.Message的引用。如果你只是字符串s;你会得到警告。

答案 2 :(得分:1)

我认为回答这个问题的人需要深入了解编译器的工作原理。但是,像FxCop这样的东西可能会抓住这个。

答案 3 :(得分:1)

属性只是方法,没有什么可以阻止任何人在ex.Message属性中放置一些代码。因此,虽然你可能没有对s做任何事情,但调用ex.Message COULD可能有价值......

答案 4 :(得分:1)

当变量可能使用或不使用时,编译每个实例和极端情况并不是编译器的工作。有些很容易发现,有些则更成问题。谨慎的做法是明智的做法(特别是当警告可以被设置为错误时 - 想象一下软件是否因为编译器认为你没有使用你的东西而不能编译)。 Microsoft Compiler团队专门说:

  

“...我们对客户的指导   有兴趣发现未使用的   他们的代码中的元素是使用   的FxCop。它可以发现未使用的字段   还有更多有趣的数据   你的代码。“

- Ed Maurer, Development Lead, Managed Compiler Platform

答案 5 :(得分:1)

Resharper会抓住那个

答案 6 :(得分:0)

静态分析在今天可以完成的任务中受到限制。 (虽然埃里克指出不是因为在这种情况下它不知道。)

.NET 4中的新代码契约大大增强了静态检查,有一天我确信你会得到更多有关此类明显错误的帮助。

如果你已经尝试过代码契约,那么你会知道对代码进行详尽的静态分析并不容易 - 它可以在每次编译后抖动几分钟。静态分析是否能够在编译时找到这样的每个问题?可能不是:见http://en.wikipedia.org/wiki/Halting_problem