“ [Classname]”是NameSpaceA。[Classname]和NamespaceB之间的模糊引用。[Classname]

时间:2018-11-14 06:37:00

标签: c#

已知的变体形式:

'Font' is an ambiguous reference between System.Drawing.Font and iTextSharp.text.Font

'Timer'是[4个命名空间中的任何一个]之间的不明确引用。

'Message' is an ambiguous reference between 'ThreeDSeekUtils.Message' and 'System.Web.Services.Description.Message'

'chart' is an ambiguous reference between 'tool.2dChartLib.chart' and 'tool.3dChartLib.chart'

为什么会出现此编译器错误以及如何解决?

P.S .:如果您现在还没有意识到,这是回答我自己有关文档目的问题的情况。当您问一个问题时,这是显式选项:“回答您自己的问题– share your knowledge, Q&A-style

1 个答案:

答案 0 :(得分:0)

术语

使用将发挥重要作用。我将使用该单词的多种版本: 使用指令。使用块。用英语动词

由于这个问题都是关于歧义性的,因此即使使用它本身也是模棱两可的。

背景

.NET允许多个类具有相同的名称,只要它们位于不同的命名空间中即可-只要它们的完全限定名称(名称空间+类名称)不同即可。 System.Threading.TimerSystem.Timers.Timer的区别与System.String的区别。

在后台,编译器仅使用完全限定的名称。这是C#设计人员必须尽早做出的决定,因此他们不能在不冒着在下次编译中破坏现有代码的风险的情况下推翻它。他们仍然确实看到了不利因素,并且也考虑了这些不利因素。

每次定义类型时都要写System.String会有点烦人。每次都必须写System.Collections.Generic.List<T>是完全不可行的。两者也不利于代码的可读性。因此,这不是一般用途的东西。为了解决这个问题,添加了using directives。如果您没有给出完全限定的名称,则编译器将在所有与using一起列出的名称空间中查找该名称的类。项目临时模板是using System;自动创建的吗?这就是您可以只写StringObject而不必担心管道问题的原因。那些使用伪指令的人总是在重构?这就是这样做的原因。

出了什么问题?

尽管程序员在命名方面存在一些糟糕的选择-我特别关注的是4个Timers和此处的关键字“ using”-很少发生实际冲突。你只是赔率。由于某种原因或其他原因,存在两个或多个使用的TimerFont或类似类的命名空间。

因此,现在编译器无法找出您所指的两个候选对象中的 个。在解释您所写内容之前,需要先进行说明。不确定类型的所有功能(包括IntelliSense)都无法正常工作。特别是各种计时器在字段,属性,事件方面都有很大的不同-更不用说像重复这样的行为了。

通常,您甚至都不希望该探秘类进入范围。出于完全无关的原因,您在其中使用了using指令。在使用using System.Windows.Forms;using System.Threadin;g的情况下,Timer的情况经常会出现在文件的顶部。如果您想在过去学习Windows窗体中的多线程功能(在BackgroundWorkers,Tasks和WPF / UWP之前),就会发生这种情况。因此,您可能会突然发现它。可能是在几个编程会议之前编写的代码中。

差异

using指令与本机C ++和许多解释语言中的include不具有可比性。在链接程序步骤中,这些代码往往是实际的代码副本。如果您以这种方式考虑,那么您走错了路。

解决方案1:在这种情况下为全限定名称

虽然您不需要写完全限定的名称,但您仍然可以。而且,如果您使用完全限定的名称,则编译器无需进行任何查找。当然,仅靠这种方式不能解决经常使用的名称。

解决方案2:使用修剪

发生此问题是因为您有很多使用指令。那么摆脱一些呢?也许您可以停止使用静态使用(包括子命名空间)。也许不是类型而是只需要它实现的某些接口的属性?也许您不再需要该名称空间,因为您之前使用的名称空间类被一个完全不同的名称空间替代了?大多数IDE的重构工具可以为您提供帮助,但是您可能必须将其与解决方案3结合使用。

解决方案3:在其他地方使用标准名称

如果要删除一个名称空间,则首先删除最不重要的名称空间会更容易。如果您学习Windows窗体中的多任务处理,则可能需要System.Threading更多System.Windows.Forms。在仅添加多任务的项目中,可能是相反的情况。您可以使用var消除变量声明+赋值的左侧,这可能会减少这种情况。

如果您这样做,则可以完全摆脱问题。

解决方案3:将其移近使用位置

默认情况下,uses的作用域是整个sorucecode文件,但可以将它们放在任何括号中,以限制为该括号。这很少使用,经常被忽略-我不确定这是一种可以接受的写作风格。我仍然觉得有必要提及该选项以保持完整性。

精炼1:键入别名

尽管使用指令是解决完全限定名称的主要方法,但并不是唯一的名称。类型别名也是一个选项。令人困惑的是,它们是using指令本身的一个子案例。幸运的是,它们的语法是如此不同,应该没有混淆的可能。

如果使用别名,则只需要在定义别名的位置使用标准名称即可。将别名明确命名为TimerWindowsFormsFontFromSystem.,突然之间,您只需要在一个地方输入完全限定的名称即可。

仍然有很多其他原因使用类型别名。

改进2:子类化

尽管我不确定在任何情况下都不能使用Type别名,但仍会出现这种情况。毕竟,我们正在谈论的是不太可能发生的事情。也许就像别名一样,无论如何,您还是必须这样做(出于其他原因)(我知道WPF / XAML中有1种情况)。

如果您编写类似class FormsTimer : System.Windows.Forms.Timer { }的内容,则会创建一个新类,其行为与System.Windows.Forms.Timer完全相同-但却是完全不同的完全限定名称。