0

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

[DataContract]
public class MyDataContractClass {}

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

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

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

using System.Runtime.Serialization;

System.Runtime.Serialization到类上方的同一个文件,但直到我在项目资源管理器中添加对的引用,问题才会消失。

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

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

4

3 回答 3

5

您会收到相同的错误消息,因为就编译器而言,这是相同的问题:它找不到您所指的类型。在不知道您要引用哪种类型的情况下,它不知道您是否缺少using指令或引用 - 这是一种 catch-22 情况。

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

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

  • 确保您有对适当程序集的引用
  • 确保您有适当的using指令

您已经获得了找出问题所在所需的所有信息。编译器没有。

当然,如果也不知道你指的是哪种类型,那么期望编译器会是非常不合理的。

于 2011-03-22T07:53:46.960 回答
5

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

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


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

  • 知道在上一次编译尝试期间发出的错误消息
  • 知道已更改的源文件的先前状态和当前状态
  • 假设在两者之间添加的任何文本都是您尝试解决任何/所有以前的错误
  • 然后更改它的搜索策略,使其仅在新的 using 语句中搜索以前未解析的类型名称。
于 2011-03-22T07:55:16.850 回答
2

实际上,我认为错误消息对问题和解决方案都有很好的描述。警告状态are you missing a using directive or an assembly reference?,你确实错过了两者。

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

为了回避这个问题,ReSharper 有一个很好的功能,可以在需要时自动添加引用。

于 2011-03-22T07:54:33.553 回答