14.1 一般規定
C# 程式是使用命名空間來組織。 命名空間既做為程式的「內部」組織系統,又做為「外部」組織系統,用來呈現向其他程式公開的程序元素。
提供 using 指示詞 (§14.5) 以方便使用命名空間。
14.2 編譯單位
compilation_unit由零個或多個 extern_alias_directives 組成,後接著零個或多個 using_directives,後接著零個或多個 global_attributes,後面接著零個或多個 namespace_member_declarations。 compilation_unit定義了輸入的整體結構。
compilation_unit
: extern_alias_directive* using_directive* global_attributes?
namespace_member_declaration*
;
C# 程式是由一或多個編譯單位所組成。 編譯 C# 程式時,所有編譯單位都會一起處理。 因此,編譯單位可以彼此相依,可能以迴圈方式。
編譯單元的 extern_alias_directive會影響該編譯單元的 using_directive、 global_attributes 和 namespace_member_declaration,但對其他編譯單元沒有影響。
編譯單元的 using_directive會影響該編譯單元的 global_attributes 和 namespace_member_declaration,但對其他編譯單元沒有影響。
編譯單元的 global_attributes (§23.3) 允許指定目標組件和模組的屬性。 元件和模組可作為類型的實體容器。 元件可能包含數個實體個別的模組。
程式每一個編譯單元的 namespace_member_declarations 會將成員提供至稱為廣域名稱空間的單一宣告空間。
Example:
// File A.cs: class A {} // File B.cs: class B {}這兩個編譯單位會貢獻單一全域命名空間,在此案例中,宣告兩個具有完整名稱和
AB的類別。 由於這兩個編譯單位會參與相同的宣告空間,因此如果每個單位都包含同名成員的宣告,就會發生錯誤。結束範例
14.3 命名空間宣告
namespace_declaration由關鍵字命名空間組成,後面接著命名空間名稱和內文,後面接著分號(選擇性)。
namespace_declaration
: 'namespace' qualified_identifier namespace_body ';'?
;
qualified_identifier
: identifier ('.' identifier)*
;
namespace_body
: '{' extern_alias_directive* using_directive*
namespace_member_declaration* '}'
;
namespace_declaration可能以compilation_unit中的頂層宣告或另一個namespace_declaration內的成員宣告的形式出現。 當 namespace_declaration 發生為 compilation_unit中的最上層宣告時,命名空間會成為全域命名空間的成員。 當 namespace_declaration 發生在另一個 namespace_declaration內時,內部命名空間會成為外部命名空間的成員。 不論是哪一種情況,命名空間的名稱都應該在包含的命名空間內是唯一的。
命名空間是隱含的 public ,命名空間的宣告不能包含任何存取修飾詞。
在 namespace_body內,選用 using_directive會匯入其他命名空間、類型和成員的名稱,允許直接參照它們,而不是透過限定名稱。 選擇性 namespace_member_declarations 將成員貢獻給命名空間的宣告空間。 請注意,所有 using_directive應出現在任何成員聲明之前。
namespace_declaration的qualified_identifier可以是單一標識符或以“.”標記分隔的標識符序列。 後者形式允許程式定義巢狀命名空間,而不需要語彙巢狀數個命名空間宣告。
Example:
namespace N1.N2 { class A {} class B {} }在語意上相當於
namespace N1 { namespace N2 { class A {} class B {} } }結束範例
命名空間是開放式的,兩個具有相同完整名稱的命名空間宣告 (§7.8.3) 會貢獻相同的宣告空間 (§7.3)。
範例:在下列程式代碼中
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }上述的兩個命名空間宣告會貢獻相同的宣告空間,在此案例中,宣告兩個具有完整名稱和
N1.N2.AN1.N2.B的類別。 由於這兩個宣告會參與相同的宣告空間,因此如果每個宣告都包含同名成員的宣告,就會發生錯誤。結束範例
14.4 Extern 別名指示詞
extern_alias_directive引入了一個識別碼,作為命名空間的別名。 別名命名空間的規格是程式碼的外部,也適用於別名命名空間的巢狀命名空間。
extern_alias_directive
: 'extern' 'alias' identifier ';'
;
extern_alias_directive的範圍延伸到其直接包含的compilation_unit或namespace_body的using_directive、global_attributes和namespace_member_declaration。
在包含 extern_alias_directive的編譯單位或命名空間主體中, extern_alias_directive 引進的識別碼可用來參考別名命名空間。
識別碼是單字 global的編譯時錯誤。
extern_alias_directive引入的別名與using_alias_directive引入的別名非常相似。 有關extern_alias_directive和using_alias_directive的更詳細討論,請參閱 §14.5.2。
alias是內容關鍵字 (§6.4.4) ,只有在extern中緊接在關鍵字後面時才具有特殊意義。
如果程式宣告未提供外部定義的extern別名,就會發生錯誤。
範例: 下列程式宣告並使用兩個 extern 別名,
X和Y,每一個都代表不同命名空間階層的根目錄:extern alias X; extern alias Y; class Test { X::N.A a; X::N.B b1; Y::N.B b2; Y::N.C c; }程式會宣告外部別名
X和Y的存在,但別名的實際定義位於程式外部。 同名N.B類別現在可以當做X.N.B和Y.N.B參考,或使用命名空間別名限定符X::N.B和Y::N.B。 結束範例
14.5 Using 指示詞
14.5.1 一般規定
using 指示詞有助於使用其他命名空間中定義的命名空間和類型。 使用指示詞會影響 namespace_or_type_names (§7.8) 和 simple_names (§12.8.4) 的名稱解析程式,但與宣告不同, using_directive不會將新成員提供給編譯單位或命名空間的基礎宣告空間,其中使用它們。
using_directive
: using_alias_directive
| using_namespace_directive
| using_static_directive
;
using_alias_directive (§14.5.2) 引進命名空間或類型的別名。
using_namespace_directive (§14.5.3) 會匯入命名空間的類型成員。
using_static_directive (§14.5.4) 會匯入巢狀類型和類型的靜態成員。
using_directive的範圍延伸至其直接包含的編譯單元或命名空間主體的namespace_member_declarations。 using_directive的範圍具體不包括其對等using_directive。 因此,對等 using_directive不會相互影響,並且它們的書寫順序是微不足道的。 相反地, extern_alias_directive 的範圍包括在相同編譯單元或命名空間主體中定義的 using_directive。
14.5.2 使用別名指示詞
using_alias_directive引入了一個識別碼,該識別碼可作為緊接包圍編譯單元或命名空間主體內命名空間或類型的別名。
using_alias_directive
: 'using' identifier '=' namespace_or_type_name ';'
;
在包含 using_alias_directive的編譯單位或命名空間主體中的全域屬性和成員宣告中, using_alias_directive 引進的識別碼可用來參考指定的命名空間或類型。
Example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }上述,在命名空間的成員宣告中
N3,是的A別名,N1.N2.A因此 類別N3.B衍生自 類別N1.N2.A。 藉由建立 的別名RN1.N2,然後參考R.A,即可取得相同的效果:namespace N3 { using R = N1.N2; class B : R.A {} }結束範例
在包含 extern_alias_directive的編譯單元或命名空間主體中使用指令、全域屬性和成員宣告內, extern_alias_directive 引進的識別碼可用來參考相關聯的命名空間。
範例:例如:
namespace N1 { extern alias N2; class B : N2::A {} }以上,在命名空間的成員宣告內,是一些命名空間的
N1別名,N2其定義是程式原始程式碼外部的部分命名空間。 類別N1.B衍生自 類別N2.A。 藉由建立 的別名AN2.A,然後參考A,即可取得相同的效果:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }結束範例
extern_alias_directive或using_alias_directive會在特定編譯單元或命名空間主體內提供別名,但它不會將任何新成員貢獻給基礎宣告空間。 換句話說,別名指示詞不是可轉移的,而是只會影響發生它的編譯單位或命名空間主體。
範例:在下列程式代碼中
namespace N3 { extern alias R1; using R2 = N1.N2; } namespace N3 { class B : R1::A, R2.I {} // Error, R1 and R2 unknown }別名
R1指示詞的範圍,這些指示詞引進並R2只擴充至包含它們的命名空間主體中的成員宣告,因此R1在第R2二個命名空間宣告中為未知。 不過,將別名指示詞放在包含編譯單位的 中,會導致別名在兩個命名空間宣告中變成可用:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }結束範例
compilation_unit或namespace_body中的每個extern_alias_directive或using_alias_directive都會為緊接的compilation_unit或namespace_body的別名宣告空間 (§7.3) 提供名稱。 別名指令的 識別碼 在對應的別名宣告空間內應是唯一的。 別名標識碼在全域宣告空間或對應命名空間的宣告空間內不需要是唯一的。
Example:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // Ok使用名為 的
X別名會造成錯誤,因為相同編譯單位中已經有名為X的別名。 名為Y的類別不會與名為Y的extern 別名衝突,因為這些名稱會新增至不同的宣告空格。 前者會新增至全域宣告空間,後者會新增至這個編譯單位的別名宣告空間。當別名名稱符合命名空間成員的名稱時,應適當限定其中一項的使用方式:
namespace N1.N2 { class B {} } namespace N3 { class A {} class B : A {} } namespace N3 { using A = N1.N2; using B = N1.N2.B; class W : B {} // Error: B is ambiguous class X : A.B {} // Error: A is ambiguous class Y : A::B {} // Ok: uses N1.N2.B class Z : N3.B {} // Ok: uses N3.B }在第二個命名空間主體中
N3,不合格的使用B會導致錯誤,因為N3包含名為B的成員和命名空間主體,也會宣告名稱為B的別名;同樣地, 。AN3.B類別可以參考為N3.B或global::N3.B。 別名A可用於 限定別名成員 (§14.8),例如A::B。 別名B基本上是無用的。 它不能在 qualified_alias_member 中使用,因為只有命名空間別名可以在 qualified_alias_member 中使用,並為B類型別名使用。結束範例
就像一般成員一樣, alias_directives 引進的名稱會由巢狀作用域中類似名稱的成員隱藏。
範例:在下列程式代碼中
using R = N1.N2; namespace N3 { class R {} class B: R.A {} // Error, R has no member A }宣告中的
R.A參考B會導致編譯時期錯誤,因為R參考 ,N3.R而不是N1.N2。結束範例
extern_alias_directive的書寫順序沒有意義。 同樣地, using_alias_directive的寫入順序也沒有任何意義,但所有 using_alias_directives 都應該位於相同編譯單元或命名空間主體中的所有 extern_alias_directive之後。 using_alias_directive所參考namespace_or_type_name的解析不會受到using_alias_directive本身或立即包含編譯單元或命名空間主體中其他using_directive的影響,但可能會受到緊接包含的編譯單元或命名空間主體中的extern_alias_directive影響。 換句話說,using_alias_directive的namespace_or_type_name會解析,就好像直接包含的編譯單元或命名空間主體沒有using_directives,但具有正確的extern_alias_directive集一樣。
範例:在下列程式代碼中
namespace N1.N2 {} namespace N3 { extern alias X; using R1 = X::N; // OK using R2 = N1; // OK using R3 = N1.N2; // OK using R4 = R2.N2; // Error, R2 unknown }最後一個 using_alias_directive 會導致編譯時間錯誤,因為它不受前一個 using_alias_directive的影響。 第一個 using_alias_directive 不會導致錯誤,因為 extern 別名 X 的範圍包括 using_alias_directive。
結束範例
using_alias_directive可以為任何命名空間或類型建立別名,包括它出現的命名空間,以及巢狀在該命名空間內的任何命名空間或類型。
透過別名存取命名空間或類型會產生與透過其宣告名稱存取該命名空間或類型完全相同的結果。
範例:給定
namespace N1.N2 { class A {} } namespace N3 { using R1 = N1; using R2 = N1.N2; class B { N1.N2.A a; // refers to N1.N2.A R1.N2.A b; // refers to N1.N2.A R2.A c; // refers to N1.N2.A } }名稱
N1.N2.A、R1.N2.A和R2.A都相等,且全都參考其完整名稱為N1.N2.A的類別宣告。結束範例
雖然部分類型 (§15.2.7) 的每個部分都會在相同的命名空間內宣告,但這些部分通常會寫入不同的命名空間宣告內。 因此,每個部分可以存在不同的 extern_alias_directive和 using_directive。 在一個部分內解譯簡單名稱 (§12.8.4) 時,只會考慮包含該部分的命名空間主體和編譯單元的 extern_alias_directive和 using_directive。 這可能會導致相同標識碼在不同部分有不同的意義。
Example:
namespace N { using List = System.Collections.ArrayList; partial class A { List x; // x has type System.Collections.ArrayList } } namespace N { using List = Widgets.LinkedList; partial class A { List y; // y has type Widgets.LinkedList } }結束範例
使用別名可以命名封閉的建構型別,但無法命名未系結的泛型型別宣告,而不需提供類型自變數。
Example:
namespace N1 { class A<T> { class B {} } } namespace N2 { using W = N1.A; // Error, cannot name unbound generic type using X = N1.A.B; // Error, cannot name unbound generic type using Y = N1.A<int>; // Ok, can name closed constructed type using Z<T> = N1.A<T>; // Error, using alias cannot have type parameters }結束範例
14.5.3 使用命名空間指示詞
using_namespace_directive會將命名空間中包含的類型匯入到緊接內繞的編譯單元或命名空間主體中,使每個類型的識別碼無需限定即可使用。
using_namespace_directive
: 'using' namespace_name ';'
;
在包含 using_namespace_directive的編譯單元或命名空間主體中的成員宣告內,可以直接參考指定命名空間中包含的類型。
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }上述,在命名空間中的成員宣告內
N3,直接提供的N1.N2型別成員,因此 類別N3.B衍生自 類別N1.N2.A。結束範例
using_namespace_directive會匯入指定命名空間中包含的型別,但特別不會匯入巢狀命名空間。
範例:在下列程式代碼中
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }using_namespace_directive會匯入 中包含的
N1型別,但不會匯入巢狀的N1命名空間。 因此,宣告N2.A中的 參考B會導致編譯時期錯誤,因為沒有名為N2的成員位於範圍內。結束範例
與 using_alias_directive不同, using_namespace_directive 可以匯入其識別碼已在封閉編譯單元或命名空間主體中定義的類型。 實際上, using_namespace_directive 匯入的名稱會由封閉編譯單元或命名空間主體中類似名稱的成員隱藏。
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }在這裡,在命名空間中的成員宣告中
N3,A參考N3.A而不是N1.N2.A。結束範例
因為當多個匯入的命名空間引進相同的類型名稱時,名稱可能會模棱兩可,所以 using_alias_directive 有助於消除參照的歧義。
範例:在下列程式代碼中
namespace N1 { class A {} } namespace N2 { class A {} } namespace N3 { using N1; using N2; class B : A {} // Error, A is ambiguous }
N1和 都包含N2成員A,而且 因為N3匯入兩者,A因此參考 中的N3是編譯時期錯誤。 在這種情況下,衝突可以透過對 的A引用進行限定,或透過引入選擇特定 的A來解決。 例如:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }結束範例
此外,當相同編譯單元或命名空間主體中 using_namespace_directive或 using_static_directive匯入的多個命名空間或類型包含相同名稱的類型或成員時,將該名稱作為 simple_name 的參考會被視為模稜兩可。
Example:
namespace N1 { class A {} } class C { public static int A; } namespace N2 { using N1; using static C; class B { void M() { A a = new A(); // Ok, A is unambiguous as a type-name A.Equals(2); // Error, A is ambiguous as a simple-name } } }
N1包含類型成員A,並C包含靜態欄位A,而且因為會匯入兩者,N2因此A參考為simple_name是模稜兩可的,而且是編譯階段錯誤。結束範例
就像 using_alias_directive一樣, using_namespace_directive 不會將任何新成員提供給編譯單元或命名空間的基礎宣告空間,而是只影響它出現的編譯單元或命名空間主體。
using_namespace_directive所參照的namespace_name的解析方式與using_alias_directive所參照的namespace_or_type_name相同。 因此,同一編譯單元或命名空間主體中的 using_namespace_directive不會相互影響,並且可以以任何順序寫入。
14.5.4 使用靜態指示詞
using_static_directive會將類型宣告中直接包含的巢狀類型和靜態成員匯入緊接的編譯單元或命名空間主體,讓每個成員和類型的識別碼無需限定即可使用。
using_static_directive
: 'using' 'static' type_name ';'
;
在包含 using_static_directive的編譯單位或命名空間主體中的成員宣告內,可以直接參考直接包含在指定類型宣告中的可存取巢狀類型和靜態成員 (擴充方法除外) 。
Example:
namespace N1 { class A { public class B {} public static B M() => new B(); } } namespace N2 { using static N1.A; class C { void N() { B b = M(); } } }在上述程式代碼中,命名空間中的
N2成員宣告內,直接可以使用 的靜態成員和巢狀類型N1.A,因此方法N可以參考B的 和M成員N1.A。結束範例
using_static_directive 不會直接將擴充方法匯入為靜態方法,但會讓它們可供擴充方法叫用 (§12.8.10.3) 。
Example:
namespace N1 { static class A { public static void M(this string s){} } } namespace N2 { using static N1.A; class B { void N() { M("A"); // Error, M unknown "B".M(); // Ok, M known as extension method N1.A.M("C"); // Ok, fully qualified } } }using_static_directive會匯入 中包含的
M延伸方法N1.A,但只能匯入延伸方法。 因此,編譯時間錯誤主體M中對 的第一個參考B.N會導致編譯時間錯誤,因為沒有名為M的成員位於範圍內。結束範例
using_static_directive只會匯入直接在指定類型中宣告的成員和類型,而不是在基底類別中宣告的成員和類型。
Example:
namespace N1 { class A { public static void M(string s){} } class B : A { public static void M2(string s){} } } namespace N2 { using static N1.B; class C { void N() { M2("B"); // OK, calls B.M2 M("C"); // Error. M unknown } } }using_static_directive 會匯入 中包含的
M2方法N1.B,但不會匯入 中包含的方法MN1.A。 因此,在編譯時期錯誤主體中,對的M參考C.N會導致編譯時間錯誤,因為沒有名為M的成員位於範圍內。 開發人員必須新增第二using static個指示詞,以N1.A指定 中的方法也應該匯入。結束範例
多個 using_namespace_directives 和 using_static_directives 之間的歧義在 §14.5.3 中討論。
14.6 命名空間成員宣告
namespace_member_declaration是namespace_declaration (§14.3) 或type_declaration (§14.7)。
namespace_member_declaration
: namespace_declaration
| type_declaration
;
編譯單元或命名空間主體可以包含 namespace_member_declaration,而這類宣告會將新成員提供給包含編譯單元或命名空間主體的基礎宣告空間。
14.7 類型宣告
type_declaration是class_declaration (§15.2)、struct_declaration (§16.2)、interface_declaration (§19.2)、enum_declaration (§20.2) 或delegate_declaration (§21.2)。
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_declaration
;
type_declaration可以作為編譯單元中的最上層宣告發生,也可以作為命名空間、類別或結構內的成員宣告發生。
當類型的 T 類型宣告發生為編譯單元中的最上層宣告時,類型宣告的完整名稱 (§7.8.3) 與宣告的非限定名稱 (§7.8.2) 相同。 當類型的 T 類型宣告發生在命名空間、類別或結構宣告內時,類型宣告的完整名稱 (§7.8.3) 是 S.N,其中 S 是包含命名空間、類別或結構宣告的完整名稱,而且 N 是宣告的非限定名稱。
在類別、介面或結構內宣告的類型稱為巢狀類型 (§15.3.9) 。
類型宣告的允許存取修飾詞和預設存取取決於發生宣告的內容 (§7.5.2):
- 在編譯單位或命名空間中宣告的類型可以具有
public或internal存取權。 預設值為internal存取權。 - 類別中宣告的類型可以有
public、、protected internal、protected、private protected、internal或private存取。 預設值為private存取權。 - 結構中宣告的類型可以有
public、internal或private存取。 預設值為private存取權。
14.8 限定別名成員
14.8.1 一般規定
命名空間別名限定符::可讓您保證類型名稱查閱不受新類型和成員的引進影響。 命名空間別名限定符一律會出現在兩個稱為左側和右手標識碼的標識碼之間。 不同於一般 . 限定符,限定符的 :: 左側標識符只會查閱為extern或使用別名。
qualified_alias_member提供對全域命名空間的明確存取,以及 extern 或使用可能被其他實體隱藏的別名。
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
qualified_alias_member可以用作namespace_or_type_name (§7.8) 或作為member_access中的左操作數 (§12.8.7)。
qualified_alias_member由兩個識別碼組成,稱為左側和右側識別碼,由權杖分隔::,並選擇性地後面接著type_argument_list。 當左側標識碼是全域時,就會搜尋全域命名空間來尋找右側標識符。 對於任何其他左側標識符,該標識符會查閱為外部或使用別名 (§14.4 和 §14.5.2) 。 如果沒有這類別名或別名參考類型,就會發生編譯時期錯誤。 如果別名參考命名空間,則會搜尋該命名空間的右側標識符。
qualified_alias_member有兩種形式之一:
-
N::I<A₁, ..., Aₑ>,其中N和I代表標識碼,而<A₁, ..., Aₑ>是類型自變數清單。 (e一律至少是一個。 -
N::I,其中N和I表示標識碼。 (在此情況下,e被視為零。
使用此符號, qualified_alias_member 的含義確定如下:
- 如果
N是識別碼global,則會搜尋I全域命名空間:- 如果全域命名空間包含名為
I且e為零的命名空間,則 qualified_alias_member 會參考該命名空間。 - 否則,如果全域命名空間包含名為
I的非泛型類型,e且為零,則 qualified_alias_member 會參考該類型。 - 否則,如果全域命名空間包含具有
I類型參數的名為e的類型,則qualified_alias_member會參考使用指定類型引數所建構的類型。 - 否則, qualified_alias_member 未定義,且會發生編譯階段錯誤。
- 如果全域命名空間包含名為
- 否則,從立即包含qualified_alias_member (如果有的話) 命名空間宣告 (§14.3) 開始,繼續每個封閉命名空間宣告 (如果有的話) ,並以包含qualified_alias_member的編譯單位結束,會評估下列步驟,直到找到實體為止:
- 如果命名空間宣告或編譯單元包含將 N 與類型相關聯的 using_alias_directive ,則 qualified_alias_member 未定義,且會發生編譯時間錯誤。
- 否則,如果命名空間宣告或編譯單位包含與命名空間相關聯的extern_alias_directive或
N,則:- 如果相關
N聯的命名空間包含名為I的命名空間,e且為零,則 qualified_alias_member 會參考該命名空間。 - 否則,如果相關
N聯的命名空間包含名為I的非泛型類型,e且為零,則 qualified_alias_member 會參考該類型。 - 否則,如果相關
N聯的命名空間包含具有I類型參數的名為e的類型,則qualified_alias_member會參考使用指定類型引數建構的類型。 - 否則, qualified_alias_member 未定義,且會發生編譯階段錯誤。
- 如果相關
- 否則, qualified_alias_member 未定義,且會發生編譯階段錯誤。
範例:在程式碼中:
using S = System.Net.Sockets; class A { public static int x; } class C { public void F(int A, object S) { // Use global::A.x instead of A.x global::A.x += A; // Use S::Socket instead of S.Socket S::Socket s = S as S::Socket; } }
A類別是以global::A參考,且型System.Net.Sockets.Socket別會使用S::Socket參考。 使用A.x和S.Socket會改為造成編譯時間錯誤,因為A和S會解析為參數。結束範例
注意:只有當用作
global的左側識別碼時,識別碼才具有特殊意義。 它不是關鍵字,也不是別名;它是一個上下文關鍵字 (§6.4.4)。 在程式碼中:class A { } class C { global.A x; // Error: global is not defined global::A y; // Valid: References A in the global namespace }using
global.A會造成編譯時期錯誤,因為範圍中沒有名為global的實體。 如果某些名為 global 的實體位於範圍中,則global中的global.A會解析為該實體。使用
global作為 qualified_alias_member 的左側識別碼一律會導致命名空間中的global查閱,即使有名為global的 using 別名也一樣。 在程式碼中:using global = MyGlobalTypes; class A { } class C { global.A x; // Valid: References MyGlobalTypes.A global::A y; // Valid: References A in the global namespace }
global.A解析為MyGlobalTypes.A,並global::A解析為全域命名空間中的 類別A。結尾註釋
14.8.2 別名的唯一性
每個編譯單位和命名空間主體都有個別的宣告空間,用於外部別名和使用別名。 因此,雖然extern別名或使用別名的名稱在extern別名集合內必須是唯一的,而且使用在包含編譯單位或命名空間主體的中宣告的別名,只要別名只能與 :: 限定符搭配使用,別名就可以擁有與類型或命名空間相同的名稱。
範例:在下列內容中:
namespace N { public class A {} public class B {} } namespace N { using A = System.IO; class X { A.Stream s1; // Error, A is ambiguous A::Stream s2; // Ok } }名稱
A在第二個命名空間主體中有兩個可能的意義,因為 類別A和using別名A都在範圍內。 基於這個理由,A在限定名稱A.Stream中使用 是模棱兩可的,並會導致發生編譯時間錯誤。 不過,搭配A限定符使用::不是錯誤,因為A只會查閱為命名空間別名。結束範例