|
|
|
|
|
在C#中,訪問嵌套命名空間的類的時候,你如果是一個新手,或者對C#嵌套命名空間的了解還不夠透徹,那么就有可能出現(xiàn)如本文中的錯誤。
問題
有如下嵌套命名空間代碼:
namespace n1
{
namespace n2
{
class foo{}
}
}
我用如下寫法調(diào)用類foo:
using n1;
n2.foo something;
但是這樣寫不對!
那么該如何寫才對呢?
解答一
這是 C# 的規(guī)則,如果你這樣做:
namespace Frobozz
{
namespace Magic
{
class Lamp {}
}
class Foo
{
Magic.Lamp myLamp; // 合規(guī);
}
}
那是合規(guī)的,當Magic在Frobozz里時,Magic的意思是Frobozz.Magic。但下面代碼不是:
namespace Frobozz
{
namespace Magic
{
class Lamp {}
}
}
namespace Flathead
{
using Frobozz;
class Bar
{
Magic.Lamp myLamp; // 不合規(guī)
}
}
這是不合規(guī)的,僅僅使用Frobozz并不能將Magic帶入范圍。
描述這一點的 C# 規(guī)則在 C# 4 規(guī)范的第 7.6.2 節(jié)中。這是一個非?;靵y的部分;你想要的是靠近末尾的段落:
否則,如果命名空間聲明的 using-namespace-directives 導入的命名空間恰好包含一個名稱為 ... 的類型......
關鍵是它說的是“恰好是一種類型”,而不是“恰好是一種類型或命名空間”。當你在該名稱空間之外時,我們不允許你像這樣“切片”命名空間名稱,因為它可能會造成混淆。正如其他人所說,如果你想做那種事情,請在使用別名(using-alias)指令中完全限定一次,然后使用別名。
使用命名空間別名:
using n2 = n1.n2;
...
n2.foo something;
類名之前應該是一個完整的命名空間(帶有/或嵌套類型的其他類名),截斷的命名空間將不起作用。
解答二
通過設計,命名空間可以幫助你定義范圍。
除非你完全限定它,否則你會得到你所看到的錯誤。
假設你有這樣的代碼:
namespace n1
{
namespace n2
{
class Foo { }
}
}
你可以通過兩種方式執(zhí)行此操作。
代碼:
namespace n3
{
using n1.n2;
class TestClass
{
private Foo something;
}
}
代碼:
namespace n3
{
using n2 = n1.n2;
class TestClass
{
private n2.Foo something;
}
}
解答三
C# 語言規(guī)范中的第 9.4.2 節(jié)第 4 段明確解釋了此行為:
using-namespace-directive導入給定命名空間中包含的類型,但特別是不導入嵌套的命名空間。
它甚至繼續(xù)舉了一個與你自己的非常相似的例子。
namespace N1.N2
{
class A {}
}
namespace N3
{
using N1;
class B: N2.A {} // 錯誤, N2未知
}
然而,如果你把代碼改為這樣:
namespace n1
{
public class Example
{
public static void Main()
{
n2.Foo a; // 這是合規(guī)的
}
}
}
這將編譯,因為n2是可訪問的,它是從原型命名空間塊中引用的。
解答四
一種方法是將嵌套的命名空間聲明為類。
比如你有如下代碼:
namespace NS1
{
public class NNS1
{
public class C { }
}
}
namespace NS2
{
public class NNS2
{
public class C { }
}
}
然后通過以下方式使用你的命名空間:
using NS1;
using NS2;
class C
{
public C()
{
var c1 = new NNS1.C();
var c2 = new NNS2.C();
}
}
但是,這不能創(chuàng)建命名空間的聯(lián)合,如果你有:
namespace NS1
{
public class NNS
{
public class C1 { }
}
}
namespace NS2
{
public class NNS
{
public class C2 { }
}
}
和
using NS1;
using NS2;
class C
{
public C()
{
var c1 = new NNS.C1();
var c2 = new NNS.C2();
}
}
編譯器會認為NNS有歧義義,因為它可以在這個上下文中引用兩個類符號。我試圖將命名空間聲明為接口,并使用一個類來實現(xiàn)它們以創(chuàng)建命名空間的聯(lián)合,但是,實現(xiàn)接口不會自動在其中導入嵌套類符號。
相關文章