|
|
|
|
|
在C#中,訪問嵌套命名空間的類的時(shí)候,你如果是一個(gè)新手,或者對(duì)C#嵌套命名空間的了解還不夠透徹,那么就有可能出現(xiàn)如本文中的錯(cuò)誤。
問題
有如下嵌套命名空間代碼:
namespace n1
{
namespace n2
{
class foo{}
}
}
我用如下寫法調(diào)用類foo:
using n1;
n2.foo something;
但是這樣寫不對(duì)!
那么該如何寫才對(duì)呢?
解答一
這是 C# 的規(guī)則,如果你這樣做:
namespace Frobozz
{
namespace Magic
{
class Lamp {}
}
class Foo
{
Magic.Lamp myLamp; // 合規(guī);
}
}
那是合規(guī)的,當(dāng)Magic在Frobozz里時(shí),Magic的意思是Frobozz.Magic。但下面代碼不是:
namespace Frobozz
{
namespace Magic
{
class Lamp {}
}
}
namespace Flathead
{
using Frobozz;
class Bar
{
Magic.Lamp myLamp; // 不合規(guī)
}
}
這是不合規(guī)的,僅僅使用Frobozz并不能將Magic帶入范圍。
描述這一點(diǎn)的 C# 規(guī)則在 C# 4 規(guī)范的第 7.6.2 節(jié)中。這是一個(gè)非?;靵y的部分;你想要的是靠近末尾的段落:
否則,如果命名空間聲明的 using-namespace-directives 導(dǎo)入的命名空間恰好包含一個(gè)名稱為 ... 的類型......
關(guān)鍵是它說的是“恰好是一種類型”,而不是“恰好是一種類型或命名空間”。當(dāng)你在該名稱空間之外時(shí),我們不允許你像這樣“切片”命名空間名稱,因?yàn)樗赡軙?huì)造成混淆。正如其他人所說,如果你想做那種事情,請(qǐng)?jiān)谑褂脛e名(using-alias)指令中完全限定一次,然后使用別名。
使用命名空間別名:
using n2 = n1.n2;
...
n2.foo something;
類名之前應(yīng)該是一個(gè)完整的命名空間(帶有/或嵌套類型的其他類名),截?cái)嗟拿臻g將不起作用。
解答二
通過設(shè)計(jì),命名空間可以幫助你定義范圍。
除非你完全限定它,否則你會(huì)得到你所看到的錯(cuò)誤。
假設(shè)你有這樣的代碼:
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導(dǎo)入給定命名空間中包含的類型,但特別是不導(dǎo)入嵌套的命名空間。
它甚至繼續(xù)舉了一個(gè)與你自己的非常相似的例子。
namespace N1.N2
{
class A {}
}
namespace N3
{
using N1;
class B: N2.A {} // 錯(cuò)誤, N2未知
}
然而,如果你把代碼改為這樣:
namespace n1
{
public class Example
{
public static void Main()
{
n2.Foo a; // 這是合規(guī)的
}
}
}
這將編譯,因?yàn)?strong>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();
}
}
編譯器會(huì)認(rèn)為NNS有歧義義,因?yàn)樗梢栽谶@個(gè)上下文中引用兩個(gè)類符號(hào)。我試圖將命名空間聲明為接口,并使用一個(gè)類來實(shí)現(xiàn)它們以創(chuàng)建命名空間的聯(lián)合,但是,實(shí)現(xiàn)接口不會(huì)自動(dòng)在其中導(dǎo)入嵌套類符號(hào)。
相關(guān)文章