2017-06-13 76 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;

要創建一個命名空間或類型

相關問題