【问题标题】:Why a declaration doesn't give a CS0201 compiler error?为什么声明不会给出 CS0201 编译器错误?
【发布时间】:2018-05-24 17:15:07
【问题描述】:

我对编译器错误 CS0201 的术语感到困惑。它说

只有赋值、调用、递增、递减和新建对象 表达式可以用作语句

因此,根据这一点,除上述之外的任何内容都不能成为陈述。那么下面一行如何不产生上述错误。

Anyclass obj;

这里我们没有任何赋值或调用或递增或递减或新对象表达式。

我知道我遗漏了一些东西,因为 official documentation 通过说声明也是一个声明来反驳这个错误。

【问题讨论】:

  • @TJWolschon OP 说根据他对文档的阅读,它不应该编译。
  • 这是一个声明,不属于“新对象”的范畴吗?
  • 我不觉得我们对这样的事情有任何了解。每个人都知道文档并不总是 100% 准确,就像在这种情况下一样。我不认为讨论本身不好,事实上,它是一个好的,但它需要是正确的设置和观众。这里很少有人能够影响文档(除了一些在 SO 上闲逛的微软员工)。如果你愿意,你也可以提交 PR 来解决这个问题。
  • @TJWolschon 这不是关于文档,而是关于编译器错误。
  • @TJWolschon 文档托管在 Github 上。你可以自己做一个拉取请求。

标签: c# oop


【解决方案1】:

错误文本是:

只有赋值、调用、递增、递减和新对象表达式可以作为语句使用

您的问题包括断言:

因此,根据这一点,除上述之外的任何内容都不能成为陈述。

不,这是一个错误的结论。

首先,您所做的只是一个坏主意。 不要阅读错误消息来了解该语言的规则。错误消息是为了告诉您不合法的程序出了什么问题。它们并非旨在作为合法的指南!错误消息的编写假设上下文是您在阅读错误的同时正在查看非法程序。错误信息是一个句子;语言规范长达 800 页,并且包含更多细节。 阅读规范

第二:一个正确的结论是:根据那个错误信息,没有其他的表达式可以作为陈述。此错误消息仅在预期语句的上下文中使用无效表达式的上下文中产生。

那么下面一行怎么不产生上述错误呢。

Anyclass obj;

该行不是表达式,因此错误消息不适用于它。

您从该错误消息中得出了错误的结论,这证明该错误消息令人困惑,仅出于这个原因,我们就可以争辩它可以更改。例如,我们可以说“表达式语句”而不是“语句”。或者我们可以诊断更大的问题,并报告“此语句包含一个通常仅对其值有用的表达式,该表达式被丢弃。仅递增......”,现在消息的目的变得更加清晰。

C# 中有很多令人困惑的错误消息。例如,考虑一下我个人最喜欢的:

params 参数必须是形参列表中的最后一个参数

如果你不知道 params 参数是如何工作的,那么从这个错误消息中得出(params int[] x, params int[] y) 是合法的结论是合理的——毕竟,params 参数是形式参数列表中的最后一个参数!得出(int x) 错误的结论也是明智的,因为params 参数不是该列表中的最后一个参数!

当然我们知道错误消息的意思是“如果你有一个params参数,那么那个参数必须是形式参数列表中的最后一个”。

错误消息是任何编译器最重要的输出之一,但它们通常令人困惑、不合语法、深奥且无用。这是为什么呢?

  • 编译器作者不是英语专业的。
  • 编写编译器错误消息时通常考虑到编译器编写者的方便,而不是用户的方便。示例:我花了数周时间改进涉及 lambda 的问题的重载解析错误消息报告逻辑,以便将 LINQ 添加到 C# 3 不会使错误消息产生误导。那是大量的工作,它占用了本可以花在其他工作上的精力。
  • 编译器编写者是领域专家,他们发现很难回到“初学者思维”。

但最难的:

  • 要编写错误消息,编译器编写者必须想象自己处于犯了错误的人的心理状态,并弄清楚如何消除错误的心理状态 一种导致编写正确程序的方式。这是人类心理学中的一个难题!编译器编写者不是读心者,但他们被要求始终如此。

所以这里发生的是:编译器期待一个语句。它找到了expression ;,它看起来像一个表达式语句。但是表达式语句中只有表达式的子集是合法的;如果不是其中之一,则报告此错误。


如果您对如何改进错误消息有任何想法,请不要在此处报告;在 Roslyn github 论坛上开始讨论。


说到这:你引用的错误信息错误的。当 await 添加到语言中时,它从未更新过。 await x 是一个表达式,await x; 是合法的。

【讨论】:

  • 那么,在语句和表达式之间,哪个是另一个的超类型,或者它们甚至是相互关联的。 “那行不是表达式,因此该语句不适用于它” 那么如果不是语句或表达式,这行是什么样的呢?谢谢
  • @SwanandPangam:statementexpression 之间没有“是一种”关系。 表达式语句是一种语句。 C# 编译器检测 expression; 形式的代码片段,如果表达式在表达式语句中不合法,则会给出此错误。
  • @SwanandPangam:声明 X x; 是声明声明。这是一种说法。但X x 不是表达式,因此语句中关于有效表达式的错误消息不适用于它。
  • “所以任何一行都应该是一个语句,或者如果它是一个表达式,那么它应该是赋值、调用、递增、递减或新对象”这是我能得出的最接近的结果。
  • @SwanandPangam:不。首先,不要再想“线条”了。行在 C# 中不是一个东西。方法的主体由零个或多个语句组成。 表达式语句是一种语句。表达式语句的形式为expression;,但表达式 必须是递增、递减等。如果您尝试编写看起来像表达式的语句,但由于其表达式类型错误而不合法,则会产生错误。
猜你喜欢
  • 2016-05-13
  • 2017-03-11
  • 2017-11-09
  • 1970-01-01
  • 2013-08-10
  • 2023-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多