Globalna dyrektywa "using"
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są przechwytywane w odpowiednich spotkania projektowego języka (LDM).
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Problem z czempionem: https://github.com/dotnet/csharplang/issues/3428
Składnia dyrektywy using została rozszerzona o opcjonalne słowo kluczowe global
, które może poprzedzać słowo kluczowe using
.
compilation_unit
: extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
;
global_using_directive
: global_using_alias_directive
| global_using_namespace_directive
| global_using_static_directive
;
global_using_alias_directive
: 'global' 'using' identifier '=' namespace_or_type_name ';'
;
global_using_namespace_directive
: 'global' 'using' namespace_name ';'
;
global_using_static_directive
: 'global' 'using' 'static' type_name ';'
;
- global_using_directives są dozwolone tylko na poziomie jednostki kompilacji (nie można ich używać w namespace_declaration).
- global_using_directives, jeśli istnieje, musi poprzedzać jakiekolwiek using_directives.
- Zakres global_using_directiverozciąga się na deklaracje namespace_member_declarationwe wszystkich jednostkach kompilacji w programie. Zakres global_using_directive nie obejmuje innych global_using_directives. W związku z tym element równorzędny global_using_directives lub z innej jednostki kompilacji nie ma wpływu na siebie, a kolejność, w jakiej są zapisywane, jest nieistotna. Zakres global_using_directive wyraźnie nie obejmuje using_directivebezpośrednio zawartych w jakiejkolwiek jednostce kompilacji programu.
Efekt dodania global_using_directive do programu można porównać do efektu dodania podobnego using_directive, który odnosi się do tej samej docelowej przestrzeni nazw lub typu w każdej jednostce kompilacji programu. Jednak cel global_using_directive jest rozpoznawany w kontekście jednostki kompilacji, która go zawiera.
zakresy §7.7
Są to odpowiednie punkty punktorów z proponowanymi dodatkami (które są pogrubioną):
- Zakres nazwy zdefiniowanej przez extern_alias_directive rozciąga się na global_using_directives,using_directives, global_attributes i namespace_member_declarations bezpośrednio zawierającej jednostkę kompilacji lub treść przestrzeni nazw. extern_alias_directive nie wnosi nowych elementów członkowskich do przestrzeni deklaracji bazowej. Innymi słowy, extern_alias_directive nie jest przechodnia, ale raczej wpływa tylko na jednostkę kompilacji lub treść przestrzeni nazw, w której występuje.
- Zakres nazwy zdefiniowanej lub zaimportowanej przez global_using_directive rozciąga się na global_attributes i namespace_member_declarations wszystkich compilation_unitw programie.
§7.8 przestrzeni nazw i typów
Zmiany są wprowadzane do algorytmu określającego znaczenie namespace_or_type_name w następujący sposób.
Jest to odpowiedni punktor z proponowanymi dodatkami (przedstawione jako pogrubione).
- Jeśli namespace_or_type_name ma formę
I
lub formęI<A1, ..., Ak>
:- Jeśli
K
ma wartość zero, a namespace_or_type_name pojawia się w deklaracji metody ogólnej (§15.6), a jeśli ta deklaracja zawiera parametr typu (§15.2.3) o nazwieI
, namespace_or_type_name odnosi się do tego parametru typu. - W przeciwnym razie, jeśli namespace_or_type_name pojawia się w deklaracji typu, dla każdego typu wystąpienia
T
(§15.3.2), zaczynając od typu wystąpienia tej deklaracji typu i przechodząc do typu wystąpienia każdej otaczającej klasy lub deklaracji struktury (jeśli istnieją):- Jeśli
K
ma wartość zero, a deklaracjaT
zawiera parametr typu o nazwieI
, namespace_or_type_name odnosi się do tego parametru typu. - Jeżeli namespace_or_type_name występuje w ciele deklaracji typu, a
T
lub którykolwiek z jego typów bazowych zawiera zagnieżdżony dostępny typ o nazwieI
zK
parametrami typu, wtedy namespace_or_type_name odnosi się do typu skonstruowanego z podanymi argumentami typu. Jeśli istnieje więcej niż jeden taki typ, wybrano typ zadeklarowany w obrębie bardziej pochodnego typu. Należy pamiętać, że elementy niebędące członkami typów (stałe, pola, metody, właściwości, indeksatory, operatory, konstruktory instancji, destruktory i konstruktory statyczne) oraz członkowie typów z inną liczbą parametrów typów są ignorowani podczas określania znaczenia namespace_or_type_name.
- Jeśli
- Jeśli poprzednie kroki zakończyły się niepowodzeniem, dla każdej przestrzeni nazw
N
, począwszy od przestrzeni nazw, w której występuje namespace_or_type_name, kontynuując każdą otaczającą przestrzeń nazw (jeśli istnieje), a kończąc na globalnej przestrzeni nazw, następujące kroki są oceniane do momentu zlokalizowania jednostki:- Jeśli
K
ma wartość zero, aI
jest nazwą przestrzeni nazw wN
, wówczas:- Jeśli lokalizacja, w której występuje namespace_or_type_name, jest ujęta przez deklarację przestrzeni nazw dla
N
, a deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typem, lub dowolną deklaracją przestrzeni nazw dlaN
w programie zawiera global_using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typem, następnie namespace_or_type_name jest niejednoznaczny i występuje błąd czasu kompilacji. - W przeciwnym razie namespace_or_type_name odnosi się do przestrzeni nazw o nazwie
I
wN
.
- Jeśli lokalizacja, w której występuje namespace_or_type_name, jest ujęta przez deklarację przestrzeni nazw dla
- W przeciwnym razie jeśli
N
zawiera dostępny typ o nazwieI
i parametrach typuK
, wówczas:- Jeśli
K
ma wartość zero, a lokalizacja, w której występuje namespace_or_type_name, jest ujęta deklaracją przestrzeni nazw dlaN
, a deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typem, lub dowolną deklaracją przestrzeni nazw dlaN
w programie zawiera global_using_alias_directive, która kojarzy nazwęI
z przestrzeń nazw lub typ, następnie namespace_or_type_name jest niejednoznaczny i występuje błąd czasu kompilacji. - W przeciwnym razie namespace_or_type_name odnosi się do typu skonstruowanego przy użyciu podanych argumentów typu.
- Jeśli
- W przeciwnym razie, jeśli lokalizacja, w której występuje namespace_or_type_name, jest objęta deklaracją przestrzeni nazw dla
N
:- Jeśli
K
ma wartość zero, a deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive, która kojarzy nazwęI
z zaimportowaną przestrzenią nazw lub typem, lub dowolną deklaracją przestrzeni nazw dlaN
w programie zawiera global_using_alias_directive, która kojarzy nazwęI
z zaimportowaną przestrzenią nazw lub typem, następnie namespace_or_type_name odnosi się do tej przestrzeni nazw lub typu. - W przeciwnym razie, jeśli przestrzenie nazw i deklaracje typów importowane przez using_namespace_directiveoraz using_alias_directivew deklaracji przestrzeni nazw , a także przestrzenie nazw i deklaracje typów importowane przez global_using_namespace_directivei global_using_static_directivew dowolnej deklaracji przestrzeni nazw dla
N
w programie zawierają dokładnie jeden dostępny typ o nazwieI
i parametrach typuK
, następnie namespace_or_type_name odnosi się do tego typu skonstruowanego przy użyciu podanych argumentów typu. - W przeciwnym razie, jeśli przestrzenie nazw i deklaracje typów importowane przez using_namespace_directives i using_alias_directives z deklaracji przestrzeni nazw oraz przestrzenie nazw i deklaracje typów importowane przez global_using_namespace_directives i global_using_static_directives z dowolnej deklaracji przestrzeni nazw dla
N
w programie zawierają więcej niż jeden dostępny typ o nazwieI
zK
parametrami typu, wówczas namespace_or_type_name staje się niejednoznaczny i występuje błąd.
- Jeśli
- Jeśli
- W przeciwnym razie przestrzeń_nazw_lub_typ jest niezdefiniowana i pojawia się błąd kompilacji.
- Jeśli
Proste nazwy §12.8.4
Zmiany są wprowadzane do reguł oceny simple_name w następujący sposób.
Jest to odpowiedni punkt z proponowanymi dodatkami (które są pogrubionym ).
- W przeciwnym razie dla każdej przestrzeni nazw
N
, począwszy od przestrzeni nazw, w której występuje simple_name, kontynuując każdą otaczającą przestrzeń nazw (jeśli istnieje), a kończąc na globalnej przestrzeni nazw, następujące kroki są oceniane do momentu zlokalizowania jednostki:- Jeśli
K
ma wartość zero, aI
jest nazwą przestrzeni nazw wN
, wówczas:- Jeśli lokalizacja, w której występuje simple_name, jest ujęta przez deklarację przestrzeni nazw dla
N
, a deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typem, lub dowolną deklaracją przestrzeni nazw dlaN
w programie zawiera global_using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typem, następnie simple_name jest niejednoznaczny i występuje błąd czasu kompilacji. - W przeciwnym razie simple_name odnosi się do przestrzeni nazw o nazwie
I
wN
.
- Jeśli lokalizacja, w której występuje simple_name, jest ujęta przez deklarację przestrzeni nazw dla
- W przeciwnym razie jeśli
N
zawiera dostępny typ o nazwieI
i parametrach typuK
, wówczas:- Jeśli
K
ma wartość zero, a lokalizacja, w której występuje simple_name, jest ujęta deklaracją przestrzeni nazw dlaN
, a deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typem, lub dowolną deklarację przestrzeni nazw dlaN
w programie zawiera global_using_alias_directive, która kojarzy nazwęI
z przestrzenią nazw lub typ, następnie simple_name jest niejednoznaczny i występuje błąd czasu kompilacji. - W przeciwnym razie namespace_or_type_name odnosi się do typu skonstruowanego przy użyciu podanych argumentów typu.
- Jeśli
- W przeciwnym razie, jeśli lokalizacja, w której występuje simple_name, jest objęta deklaracją przestrzeni nazw dla
N
:- Jeśli
K
ma wartość zero, a deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive, która kojarzy nazwęI
z zaimportowaną przestrzenią nazw lub typem, lub dowolną deklaracją przestrzeni nazw dlaN
w programie zawiera global_using_alias_directive, która kojarzy nazwęI
z zaimportowaną przestrzenią nazw lub typem, następnie simple_name odnosi się do tej przestrzeni nazw lub typu. - W przeciwnym razie, jeśli przestrzenie nazw i deklaracje typów importowane przez dyrektywy using_namespace_directiveoraz using_static_directivedla deklaracji przestrzeni nazw , a także przestrzenie nazw i deklaracje typów importowane przez globalne dyrektywy global_using_namespace_directiveoraz global_using_static_directivedla dowolnej deklaracji przestrzeni nazw dla
N
w programie, zawierają dokładnie jeden dostępny typ lub statyczny element nienależący do żadnego rozszerzenia o nazwieI
iK
parametrów typu, wtedy simple_name odnosi się do tego typu lub elementu skonstruowanego przy użyciu danych argumentów typu. - W przeciwnym razie, jeśli przestrzenie nazw i typy importowane przez using_namespace_directives deklaracji przestrzeni nazw oraz przestrzenie nazw i deklaracje typów importowane przez global_using_namespace_directives i global_using_static_directives dowolnej deklaracji przestrzeni nazw dla
N
w programie zawierają więcej niż jeden dostępny typ lub statyczny element członkowski bez rozszerzenia o nazwieI
i parametrach typuK
, następnie simple_name jest niejednoznaczny i występuje błąd.
- Jeśli
- Jeśli
Wywołania metody rozszerzenia §12.8.10.3
Zmiany są wprowadzane do algorytmu, aby znaleźć najlepsze type_nameC
według poniższego schematu.
Jest to odpowiedni punkt z proponowanymi dodatkami (oznaczonymi jako w pogrubionym):
- Począwszy od najbliższej otaczającej deklaracji przestrzeni nazw, następnie przechodząc przez każdą otaczającą deklarację przestrzeni nazw, a kończąc na zawierająca jednostka kompilacji, podejmowane są kolejne próby odnalezienia zestawu rozszerzonych metod.
- Jeśli dana przestrzeń nazw lub jednostka kompilacji zawiera bezpośrednio deklaracje typów niegenerycznych
Ci
z kwalifikującymi się metodami rozszerzeniaMj
, zestaw tych metod rozszerzenia staje się zestawem kandydatów. - Jeśli typy
Ci
zaimportowane przez using_static_declarations i bezpośrednio zadeklarowane w przestrzeniach nazw importowanych przez using_namespace_directives w danej przestrzeni nazw lub jednostce kompilacji i, jeśli zawiera jednostkę kompilacji, zaimportowane przez global_using_static_declarations i bezpośrednio zadeklarowane w przestrzeniach nazw importowanych przez global_using_namespace_directives w programie bezpośrednio zawierają kwalifikujące się metody rozszerzeniaMj
, następnie zestaw tych metod rozszerzeń jest zestawem kandydatów.
- Jeśli dana przestrzeń nazw lub jednostka kompilacji zawiera bezpośrednio deklaracje typów niegenerycznych
Jednostki kompilacji §14.2
compilation_unit definiuje ogólną strukturę pliku źródłowego. Jednostka kompilacji składa się z zera lub większej liczby global_using_directive, a następnie zero lub więcej using_directive, po których następuje zero lub więcej global_attributes a następnie zero lub więcej namespace_member_declarations.
compilation_unit
: extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
;
Program w języku C# składa się z co najmniej jednej jednostki kompilacji, z których każda znajduje się w osobnym pliku źródłowym. Po skompilowaniu programu w języku C# wszystkie jednostki kompilacji są przetwarzane razem. W związku z tym jednostki kompilacji mogą zależeć od siebie, prawdopodobnie w sposób okrągły.
global_using_directivejednostki kompilacji mają wpływ na global_attributes i namespace_member_declarationwszystkich jednostek kompilacji w programie.
Alias extern §14.4
Zakres extern_alias_directive obejmuje global_using_directives,using_directives, global_attributes oraz namespace_member_declarations zawarte bezpośrednio w jednostce kompilacji lub treści przestrzeni nazw.
Używanie dyrektyw aliasu §14.5.2
Kolejność zapisywania using_alias_directives nie ma znaczenia, a rozwiązanie namespace_or_type_name, do którego odwołuje się using_alias_directive, nie wpływa na samą using_alias_directive ani na inne using_directives w bezpośrednio zawierającej jednostce kompilacji lub treści przestrzeni nazw, i, jeśli using_alias_directive jest bezpośrednio zawarty w jednostce kompilacji, nie wpływa to na global_using_directives w programie. Innymi słowy, namespace_or_type_name dla using_alias_directive jest rozpoznawany tak, jakby natychmiast zawierająca jednostka kompilacji lub treść przestrzeni nazw nie miała using_directive, a jeśli using_alias_directive jest natychmiast zawarta w jednostce kompilacji, program nie miałby global_using_directive. using_alias_directive mogą jednak być pod wpływem extern_alias_directivew bezpośrednio zawierającej jednostce kompilacji lub treści przestrzeni nazw.
Globalne używanie dyrektyw aliasu
global_using_alias_directive wprowadza identyfikator służący jako alias dla przestrzeni nazw lub typu w programie.
global_using_alias_directive
: 'global' 'using' identifier '=' namespace_or_type_name ';'
;
W deklaracjach składowych w dowolnej jednostce kompilacji programu, która zawiera global_using_alias_directive, identyfikator wprowadzony przez global_using_alias_directive może służyć do odwoływania się do danej przestrzeni nazw lub typu.
Identyfikator global_using_alias_directive musi być unikatowy w przestrzeni deklaracji dowolnej jednostki kompilacji programu, który zawiera global_using_alias_directive.
Podobnie jak zwykłe elementy członkowskie, nazwy wprowadzone za pomocą global_using_alias_directives są ukryte przez podobnie nazwane elementy członkowskie w zagnieżdżonych zakresach.
Kolejność zapisu global_using_alias_directivenie ma znaczenia, a rozwiązanie namespace_or_type_name, do którego odwołuje się global_using_alias_directive, nie ma wpływu na samą global_using_alias_directive lub przez inne global_using_directives lub using_directivew programie. Innymi słowy, namespace_or_type_nameglobal_using_alias_directive jest rozpoznawana tak, jakby natychmiast zawierająca jednostka kompilacji nie miała using_directives, a cały zawierający program nie miał global_using_directives. global_using_alias_directive może jednak być pod wpływem extern_alias_directivew bezpośrednio zawierającej jednostce kompilacji.
global_using_alias_directive może utworzyć alias dla dowolnej przestrzeni nazw lub typu.
Uzyskiwanie dostępu do przestrzeni nazw lub typu za pośrednictwem aliasu daje dokładnie taki sam wynik, jak uzyskiwanie dostępu do tej przestrzeni nazw lub typu za pośrednictwem zadeklarowanej nazwy.
Użycie aliasów może nazwać zamknięty typ skonstruowany, ale nie może nazwać niezwiązanej deklaracji typu ogólnego bez podawania argumentów typu.
Globalne używanie dyrektyw przestrzeni nazw
global_using_namespace_directive importuje typy zawarte w przestrzeni nazw do programu, umożliwiając korzystanie z identyfikatora każdego typu bez kwalifikacji.
global_using_namespace_directive
: 'global' 'using' namespace_name ';'
;
W deklaracjach składowych programu zawierającego global_using_namespace_directivemożna bezpośrednio odwoływać się do typów zawartych w danej przestrzeni nazwowej.
global_using_namespace_directive importuje typy zawarte w danej przestrzeni nazw, ale w szczególności nie importuje zagnieżdżonych przestrzeni nazw.
W przeciwieństwie do global_using_alias_directiveglobal_using_namespace_directive może importować typy, których identyfikatory są już zdefiniowane w jednostce kompilacji programu. W efekcie w danej jednostce kompilacji nazwy importowane przez wszystkie global_using_namespace_directive w programie są ukryte przez członków o podobnych nazwach w jednostce kompilacji.
Jeśli więcej niż jedna przestrzeń nazw lub typ zaimportowany przez global_using_namespace_directives lub global_using_static_directivew tym samym programie zawierają typy o tej samej nazwie, odwołania do tej nazwy jako type_name są uważane za niejednoznaczne.
Ponadto, jeśli więcej niż jedna przestrzeń nazw lub typy zaimportowane przez global_using_namespace_directivelub global_using_static_directivew tym samym programie zawierają typy lub członków o tej samej nazwie, odwołania do tej nazwy jako simple_name są uznawane za niejednoznaczne.
namespace_name, do którego odwołuje się global_using_namespace_directive, jest rozwiązany w taki sam sposób, jak namespace_or_type_name, do którego odwołuje się global_using_alias_directive. W związku z tym global_using_namespace_directivew tym samym programie nie wpływają na siebie i mogą być napisane w dowolnej kolejności.
Globalne używanie dyrektyw statycznych
global_using_static_directive importuje zagnieżdżone typy i statyczne elementy członkowskie zawarte bezpośrednio w deklaracji typu do zawierającego programu, umożliwiając użycie identyfikatorów wszystkich elementów członkowskich i typów bez konieczności kwalifikacji.
global_using_static_directive
: 'global' 'using' 'static' type_name ';'
;
W deklaracjach składowych w programie, który zawiera global_using_static_directive, dostępne zagnieżdżone typy i statyczne elementy członkowskie (z wyjątkiem metod rozszerzeń) zawarte bezpośrednio w deklaracji danego typu można odwoływać się bezpośrednio.
global_using_static_directive nie importuje metod rozszerzeń bezpośrednio jako metod statycznych, ale udostępnia je na potrzeby wywołania metody rozszerzenia.
global_using_static_directive importuje tylko członków i typy zadeklarowane bezpośrednio w danym typie, a nie członków i typy zadeklarowane w klasach bazowych.
W sekcji dotyczącej global_using_namespace_directive(powyżej) omówiono niejednoznaczności między wieloma dyrektywami global_using_namespace_directiveoraz global_using_static_directives.
Kwalifikowany członek aliasu §14.8
Zmiany są wprowadzane do algorytmu określającego znaczenie qualified_alias_member w następujący sposób.
Jest to odpowiedni punkt z proponowanymi dodatkami (które są w pogrubieniu ).
W przeciwnym razie, począwszy od deklaracji przestrzeni nazw (§14.3) natychmiast zawierającej qualified_alias_member (jeśli istnieje), kontynuując z każdą otaczającą deklaracją przestrzeni nazw (jeśli istnieje), a kończąc na jednostce kompilacji, która zawiera qualified_alias_member, następujące kroki są oceniane do momentu zlokalizowania jednostki:
- Jeśli deklaracja przestrzeni nazw lub jednostka kompilacji zawiera using_alias_directive, który kojarzy
N
z typem , albo po osiągnięciu jednostki kompilacji program zawiera global_using_alias_directive, który kojarzyN
z typem, wtedy qualified_alias_member jest niezdefiniowany i powoduje błąd kompilacji. - W przeciwnym razie, jeśli deklaracja przestrzeni nazw lub jednostka kompilacji zawiera extern_alias_directive lub using_alias_directive, która kojarzy
N
z przestrzenią nazw, *lub, gdy zostanie osiągnięta jednostka kompilacji, program zawiera global_using_alias_directive, który kojarzyN
z przestrzenią nazw, następnie:- Jeśli przestrzeń nazw skojarzona z
N
zawiera przestrzeń nazw o nazwieI
iK
jest równe zero, to qualified_alias_member odnosi się do tej przestrzeni nazw. - W przeciwnym razie jeśli przestrzeń nazw skojarzona z
N
zawiera typ niegeneryczny o nazwieI
iK
ma wartość zero, qualified_alias_member odwołuje się do tego typu. - W przeciwnym razie, jeśli przestrzeń nazw skojarzona z
N
zawiera typ o nazwieI
, który ma parametry typuK
, qualified_alias_member odnosi się do tego typu skonstruowanego z podanymi argumentami typu. - W przeciwnym razie qualified_alias_member jest niezdefiniowany i występuje błąd kompilacji.
- Jeśli przestrzeń nazw skojarzona z
- Jeśli deklaracja przestrzeni nazw lub jednostka kompilacji zawiera using_alias_directive, który kojarzy
C# feature specifications