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

时间:2011-03-22 07:50:43

标签: c# .net using

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

[DataContract]
public class MyDataContractClass {}

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

  

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

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

using System.Runtime.Serialization;

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

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

我的问题如下。这只是 设计错误的错误诊断 还是有一些 根本原因 为什么缺少上述两个步骤中的任何一个对于C#编译器发出的同一错误?

3 个答案:

答案 0 :(得分:5)

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

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

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

  • 确保您已获得对相应程序集的引用
  • 确保您有适当的using指令

您已获取了查找错误所需的所有信息。编译器没有。

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

答案 1 :(得分:5)

你不是两次做同样的事情。任何程序集都可以包含任何名称空间using语句只是引用命名空间中类型的快捷方式 - 这些类型可以由任何程序集提供。

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


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

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

答案 2 :(得分:2)

实际上,我认为错误信息非常能描述问题和解决方案。警告说明are you missing a using directive or an assembly reference?,你确实错过了两者。

至于为什么这不是两个单独的警告,当然,编译器可以查看该名称是否存在可访问类型,并发出using警告,但发出{{1}警告,如果没有。但为什么要这样呢? 这将是缓慢的,并且它几乎不会在桌面上带来额外的信息,因为程序员通常比编译器更清楚地知道他/她想做什么。

为了解决这个问题,ReSharper有一个很好的功能,可以根据需要自动添加引用。