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

Cri*_*scu 18 c# compiler-construction warnings try-catch

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

try { ... } catch (Exception ex) { }
Run Code Online (Sandbox Code Playgroud)

- >发出关于ex不使用的警告.到现在为止还挺好.

修复是这样的:

try { ... } catch (Exception ex) { string s = ex.Message; }
Run Code Online (Sandbox Code Playgroud)

看到这个,我想"很棒,所以现在编译器会抱怨s没有被使用."

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

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

try { ... } catch (Exception) { }
Run Code Online (Sandbox Code Playgroud)

要么

try { ... } catch { }
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 25

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

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

你觉得怎么样?

好吧,请考虑以下几点.

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

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

DoIt(); // discard the return value
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

这解释了一个.在许多其他情况下,我们会禁止有关从未读取的变量的警告; 我们报告警告时所有编译器策略详细说明,以及我们何时不会花费相当长的时间来编写,所以我想我会留下它.


Gar*_*Ray 9

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

  • @Gary的提示,如果你想回复别人的评论,请使用@和该人的显示名称.如果您以前未找到此功能,请参阅[此处](http://meta.stackexchange.com/questions/43019/how-do-comment-replies-work/43020#43020)以获取更多详细信息. (2认同)