为什么没有给这个未使用的变量发出警告?

在VS2010,VS2008或Windows上的MonoDevelop中编译以下程序时,我收到警告CS0219 ,“已分配变量’y’,但从未使用过它的值”。

namespace Problem { public class Program { private static void Main(string[] args) { object x = new object(); int y = 0; } } } 

在Visual Studio中编译时为什么没有x警告?

有趣的是,在Mac OS X上的MonoDevelop中编译时,我确实得到了x y CS0219警告。

事实certificate,当赋值操作的右侧不是编译时常量时,将禁止此警告。

微软Visual Studio反馈网站上一篇自那时删除的文章解释说,这是因为他们有很多投诉来自纯粹分配变量的人,所以他们可以看到调试期间返回的方法调用,并发现警告令人恼火:

在这种情况下,对“已分配但从未使用过”警告的抑制是由执行此操作的用户的反馈推动的:

 int Blah(){ // blah BlahBlah(x, y, z) // blah // blah } 

“嘿,”用户在调试时说,“我不知道BlahBlah会回来什么?” 但是没有简单的方法来检查调试器中的返回值,因此用户经常这样做:

 int Blah() { // blah int temp = BlahBlah(x, y, z) // blah // blah } 

然后使用locals或watch窗口来检查temp。 temp永远不会在函数中的任何其他地方使用,因此它产生了一个恼人的“已分配但未读取”警告。

我认为这有点遗憾:

  1. 我实际上发现这些警告在MonoDevelop中给出时很有帮助。
  2. 任何人都可以自己压制警告(诚然,他们也会压制未使用的编译时常量分配 – 可能应该有一个单独的警告?)。

无论如何,我明白你不能取悦所有人。

我可以离开这里,但我认为这是因为y只是设置,而x被实例化为非平凡的东西 – 实例化可能涉及New()方法中的单独动作,并且因为实例化变量可能有副作用,它不被认为是未使用的。 在你的情况下,它只是一个基础对象(),所以没有任何影响,但也许编译器不够聪明,无法区分。

另一方面,使用y,实例化没有副作用,因此它被认为是未使用的 – 如果完全删除应用程序的代码路径将保持不变。

我的预感是,作为一个引用类型,编译器不会显示任何警告,因为构造函数可能正在执行某些可能非常“有意义”的操作; 相比之下, y是一个值类型,其值只被赋值但从未使用过,编译器很容易告诉你,如果你不打算在线上引用它就没有意义。

Resharper还会警告您x未使用。

可能是因为x是一个引用类型,因此存储在堆上,它会阻止该对象的垃圾收集,直到x超出范围。

例如:

 void main(string[] args) { object x = new object(); while (true) { // some threading stuff // x is never garbage collected } } 

与之相反:

 void main(string[] args) { new object(); while (true) { // some threading stuff // the unreferenced object IS garbage collected } } 

Eclipse将使用未使用的案例。