为什么CS0246"无法找到类型或命名空间名称'名称'"C#错误如此令人困惑?

sha*_*oth 0 .net c# using

这是场景.我在Visual Studio中创建一个新的类库项目,添加一些类.然后在某些时候我决定我需要一些类来标记,System.Runtime.Serialization.DataContractAttribute我写下面的内容:

[DataContract]
public class MyDataContractClass {}
Run Code Online (Sandbox Code Playgroud)

当我点击编译时,我看到以下错误:

错误CS0246:找不到类型或命名空间名称"DataMember"(您是否缺少using指令或程序集引用?)

好的,问题是我忘了添加using指令以使类可见.我加

using System.Runtime.Serialization;
Run Code Online (Sandbox Code Playgroud)

到类上面的同一个文件,但问题不会消失,直到我System.Runtime.Serialization在Project Explorer中添加引用.

这非常令人困惑.为什么我必须在不同的地方添加两次相同的东西并看到相同的错误消息,无论我错过了两个步骤

我的问题如下.这只是设计错误的错误诊断,还是有一些基本原因导致错过上述两个步骤中的任何一个导致C#编译器发出的相同错误?

Jon*_*eet 5

您得到相同的错误消息,因为就编译器而言,它是同样的问题:它找不到您所指的类型.在不知道你试图引用哪种类型的情况下,它不知道你是否错过了using指令或引用 - 这是一个捕获22的情况.

您如何看待编译器应该知道它是否找不到类型,因为您错过了using指令或因为您缺少引用?它应该查看每个引用中每个命名空间中的每个类型,让你知道你错过了一个using指令吗?这可能仍然是不正确的,因为在不同的命名空间中,您实际上可能意味着完全不同的类型.(事实上​​,像Intellisense和ReSharper这样的东西愿意为你提供选择 - 编译器不能真正做到这一点.)

现在假设知道您的意思是哪种类型,问题很容易解决,因为您可以检查这两个方面:

  • 确保您已获得相应装配的参考
  • 确保你有一个合适的using指令

你已经获得了找出错误所需的所有信息.编译器没有.

当然,如果不知道你的意思是哪种类型,那么期望编译器是非常不合理的.


Dam*_*ver 5

你不是两次做同样的事情.任何程序集都可以包含任何名称空间 一个using声明只是一个快捷方式命名空间中的引用类型-而这些类型可以由任何组件提供.

系统提供的程序集中的一般约定是与命名空间同名的程序集将在该命名空间中包含大量类型 - 但是如果它不能,则编译器无法知道您忘记引用哪个程序集解析类型名称 - 它甚至不知道(直到你添加正确的程序集)DataContract在System.Runtime.Serialization命名空间中.


为了让它能够根据需要改进诊断,在编译时需要:

  • 知道在上一次编译尝试期间发出的错误消息
  • 知道已更改的源文件的先前状态和当前状态
  • 假设其间添加的任何文本都是您尝试解决任何/所有先前的错误
  • 然后更改它的搜索策略,以便它只在新的using语句中搜索以前未解析的类型名称.