2017-06-13 44 views
0

我有两个不同的命名空间,每一个Thing类:为什么在C#中添加名称空间别名可消除歧义?

namespace First.Second.Third 
{ 
    public class Thing { } 
} 

namespace Fourth.Fifth.Sixth 
{ 
    public class Thing { } 
} 

现在我尝试使用Thing其他地方,当然,编译器会抱怨,由于不明确的引用的那类:

namespace ConsoleApp1 
{ 
    using First.Second.Third; 
    using Fourth.Fifth.Sixth; 

    internal static class MainEntryPoint 
    { 
     internal static void Main(string[] args) 
     { 
      var x = new Thing(); // Complaint. 
     } 
    } 
} 

如果我向using指令中的某个命名空间添加别名,编译器错误消失:

using MyAlias = First.Second.Third; 
using Fourth.Fifth.Sixth; 

现在,编译器认为我指的是Fourth.Fifth.Sixth.Thing当我做var x = new Thing();

为什么编译器只是通过向其中一个名称空间添加别名来解决歧义问题?为什么它会自动选择我的没有的名称空间别名?

我希望这是有据可查的,并在SO和其他地方多次报道过,但我找不到答案。如果有人能帮我找到这个骗子,有人可以帮我吗?

编辑:我不是每个人都在同一页上,我猜。这里有一个真实世界的例子可能有所帮助:

如果我有两个名为“Bob”的人,并且我只是说“在这里,把这个给Bob”,你不知道该给谁。如果我说,一个是“鲍勃史密斯”,另一个是“鲍勃约翰逊”,当然我现在可以说“在这里,把这个给鲍勃史密斯。”现在,如果我说,“让我们给鲍勃·史密斯命名一个新名字:鲍勃·布拉迪”。如果我然后说“在这里,给这个”鲍勃“,这仍然是模棱两可的。请参阅我的观点?

+0

因为编译器不知道这本是一个你想使用别名? –

+0

要引用First.Second.Third,您必须将它明确地实例化为x.Thing,所以不会因为别名而产生歧义(您不直接使用名称空间)。 – Gusman

+0

我知道。我不问如何使用它。我在问为什么模棱两可会消失。 –

回答

9

我觉得你的误解是,您认为自动混叠导入类型的命名空间的。

using Fourth.Fifth.Sixth; 

使该名称空间中的所有类型都可见而不使用其他限定条件。

using MyAlias = First.Second.Third; 

什么都不做,除了给予命名一个新的名称,没有其导入。因此,如果您将using First.Second.Third;更改为using MyAlias = First.Second.Third;,则会消除歧义,因为如果没有进一步限定,Thing将从First.Second.Third不再显示。但显然其他using仍然从Fourth.Fifth.Sixth进口Thing

也可参见在C# 5.0 Language Specification相应的定义:

使用别名指示(§9.4.1)引入了一个别名命名空间 或类型。

A using-namespace-directive(§9.4.2)导入名称空间的类型成员 。

+0

嗯...现在我们正在做点什么。你能指出这个记录在哪里吗?我只想阅读规则。我正在阅读C#规范,但找不到它。 –

+0

请参阅第一句:https://msdn.microsoft.com/en-us/library/aa664765(v=vs.71).aspx – PaulF

+0

我已经阅读过。关于导入与不导入没有关系。为什么给名称空间一个昵称(别名)可以消除两个同名的类型之间的歧义? –

0

我相信你混淆x别名与x变量因为你在x中使用x的别名。 Second.Third如果你想要使用的东西,那么你应该使用

var aThing = new x.Thing();

HTH, 迈克

+0

查看我的更新。我改变了别名,没有解决任何问题。同样的问题。 –

+0

请参阅@mjwills答案。如果你使用没有别名的Thing(),那么它假定你的意思是没有别名的那个。 – Mikey

0

通过把一个别名第一个选项,你已经有效解决了模糊性(存在现在不是两个Thing - 有一个Thing和一个MyAlias.Thing)。

如果您参考Thing它将默认使用非别名版本(除非您专门使用别名)。这是完全一样的方式Console.ReadLine如果您使用using System工作。

见下文。

namespace Test 
{ 
    using MyAlias = First.Second.Third; 
    using Fourth.Fifth.Sixth; 

    public class Program 
    { 
     static void Main() 
     { 
      var x = new Thing(); // non aliased 
      var y = new MyAlias.Thing(); // aliased 
      Console.ReadLine(); 
     } 

    } 
} 

参见:

+0

我知道这是违约。我在我的问题中说过。为什么?你能指点我一些文档吗? –

+0

那么它默认为非别名,为什么如果你有'use System;'那么你可以使用'Console.ReadLine()'(即你不需要写'System.Console.ReadLine )') – mjwills

+0

我刚刚在我的一个程序中尝试了这一点,添加别名的操作使得它在任何项目被使用时都显示为红色。创建别名不仅可以让你使用别名,它还需要它。基本上First.Second.Third对编译器不可见。 – Mikey

2

这里的东西,你这样做:

using First.Second.Third; 
using Fourth.Fifth.Sixth; 

现在一切都在First.Second.ThirdFourth.Fifth.Sixth可没有他们的完全合格的名称引用。这包括Thing但是因为都包含Thing然后做new Thing()是不明确的。

如果你这样做:

using First.Second.Third; 
using MySixth = Fourth.Fifth.Sixth; 

那么只有First.Second.Third可以在不完全限定的名字来引用,命名空间Fourth.Fifth.Sixth只是又称MySixth,因此不会产生歧义。

注意的措辞: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive

对于第一种情况下,它不会说:

using System.Text;

要允许在命名空间中使用的类型,这样你就不必限定使用该名称空间中的类型

对于别名i T还没有提到名字空间使用的排位赛:

using Project = PC.MyCompany.Project;

要创建一个命名空间或类型

相关问题