Rozšíření GetEnumerator
pro podporu smyček foreach
.
Poznámka
Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.
Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v příslušných poznámkách schůzky návrhu jazyka (LDM) .
Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .
Problém šampiona: https://github.com/dotnet/csharplang/issues/3194
Shrnutí
Umožňuje smyčkám foreach
rozpoznat rozšiřující GetEnumerator
metodu, která jinak splňuje vzor foreach, a proběhnout přes výraz, pokud by jinak nastala chyba.
Motivace
To přinese foreach
do souladu s tím, jak se implementují další funkce v jazyce C#, včetně asynchronní a vzorově založené dekonstrukce.
Podrobný návrh
Změna specifikace je poměrně jednoduchá. Upravíme The foreach statement
§13.9.5 sekci na tento text:
Kompilace příkazu foreach nejprve určuje typ kolekce , typ enumerátoru a typ elementu výrazu. Toto stanovení pokračuje následujícím způsobem:
Pokud typ
X
výrazu je typ pole, existuje implicitní převod odkazu zX
na rozhraníIEnumerable
(protožeSystem.Array
implementuje toto rozhraní). typ kolekce jeIEnumerable
rozhraní, typ enumerátoru jeIEnumerator
rozhraní a typ elementu je typ prvku typu poleX
.Pokud je typ
X
výrazudynamic
pak existuje implicitní převod z výrazu na rozhraníIEnumerable
(§10.2.10). Typ kolekceje rozhraní a typ enumerátoru typ prvkuje rozhraní . Pokud je identifikátor uveden jako lokální_typ_proměnné , pakje , jinak je . V opačném případě určete, zda typ
X
má odpovídající metoduGetEnumerator
:
- Proveďte vyhledávání členů u typu
X
s identifikátoremGetEnumerator
a bez argumentů typu. Pokud vyhledávání členů nevytváří shodu nebo vytvoří nejednoznačnost nebo vytvoří shodu, která není skupinou metod, zkontrolujte výčtové rozhraní, jak je popsáno níže. Doporučuje se vydat upozornění, pokud vyhledávání členů vytvoří cokoli kromě skupiny metod nebo žádné shody.- K vyřešení přetížení použijte výslednou skupinu metod a prázdný seznam argumentů. Pokud výsledkem řešení přetížení nejsou žádné použitelné metody, výsledkem je nejednoznačnost nebo výsledkem je jedna nejlepší metoda, ale tato metoda je buď statická nebo není veřejná, zkontrolujte výčet rozhraní, jak je popsáno níže. Je doporučeno vydat varování, pokud rozlišení přetížení vytvoří cokoli jiného než jednoznačnou metodu veřejné instance nebo žádnou použitelnou metodu.
- Pokud návratový typ
E
metodyGetEnumerator
není třída, struktura nebo typ rozhraní, dojde k chybě a neprovedou se žádné další kroky.- Vyhledávání členů se provádí na
E
s identifikátoremCurrent
a bez argumentů typu. Pokud vyhledávání člena nevygeneruje žádnou shodu, výsledek je chyba nebo je výsledek cokoli kromě vlastnosti veřejné instance, která umožňuje čtení, vytvoří se chyba a neprovedou se žádné další kroky.- Vyhledávání členů se provádí na
E
s identifikátoremMoveNext
a bez argumentů typu. Pokud vyhledávání členů nevygeneruje žádnou shodu, výsledkem je chyba nebo je výsledkem cokoli kromě skupiny metod, vytvoří se chyba a neprovedou se žádné další kroky.- Rozlišení přetížení se provádí ve skupině metod s prázdným seznamem argumentů. Pokud výsledkem řešení přetížení nejsou žádné použitelné metody, vede k nejednoznačnosti nebo vede k jediné nejlepší metodě, ale tato metoda je buď statická nebo není veřejná, nebo její návratový typ není
bool
, vytvoří se chyba a neprovedou se žádné další kroky.- Typ kolekce je
X
, typ výčtu jeE
a typ elementu je typ vlastnostiCurrent
.V opačném případě zkontrolujte, zda se jedná o rozhraní s podporou výčtu:
- Pokud mezi všemi typy
Ti
, pro které existuje implicitní převod zX
naIEnumerable<Ti>
, existuje jedinečný typT
takový, žeT
nenídynamic
a pro všechny ostatníTi
existuje implicitní převod zIEnumerable<T>
naIEnumerable<Ti>
, pak typ kolekce je rozhraníIEnumerable<T>
, , typ enumerátoru jeIEnumerator<T>
rozhraní a typ prvku jeT
.- Jinak pokud existuje více takových typů
T
, dojde k chybě a neprovedou se žádné další kroky.- V opačném případě, pokud existuje implicitní převod z
X
na rozhraníSystem.Collections.IEnumerable
, pak je rozhraníSystem.Collections.IEnumerable
typem kolekce , typ enumerátoruSystem.Collections.IEnumerator
je rozhraní a typ prvkuobject
je .V opačném případě určete, jestli typ X má odpovídající metodu rozšíření
GetEnumerator
:
- Proveďte vyhledávání metody rozšíření u typu
X
s identifikátoremGetEnumerator
. Pokud vyhledávání člena nevytváří shodu nebo vytvoří nejednoznačnost nebo vytvoří shodu, která není skupinou metod, vytvoří se chyba a neprovedou se žádné další kroky. Doporučuje se vydat varování, pokud vyhledávání členů vrátí něco jiného než skupinu metod nebo žádnou shodu.- Proveďte rozlišení přetížení pomocí výsledné skupiny metod a jednoho argumentu typu
X
. Pokud rozlišení přetížení nevygeneruje žádné použitelné metody, vede k nejednoznačnosti nebo má za následek jedinou nejlepší metodu, ale tato metoda není přístupná, vytvoří se chyba bez dalších kroků.
- Toto řešení umožňuje předání prvního argumentu odkazem, pokud
X
je typ struktury a typ odkazu jein
.- Pokud návratový typ
E
metodyGetEnumerator
není třída, struktura nebo typ rozhraní, dojde k chybě a neprovedou se žádné další kroky.- Vyhledávání členů se provádí na
E
s identifikátoremCurrent
a bez argumentů typu. Pokud vyhledávání člena nevygeneruje žádnou shodu, výsledek je chyba nebo je výsledek cokoli kromě vlastnosti veřejné instance, která umožňuje čtení, vytvoří se chyba a neprovedou se žádné další kroky.- Vyhledávání členů se provádí na
E
s identifikátoremMoveNext
a bez argumentů typu. Pokud vyhledávání členů nevygeneruje žádnou shodu, výsledkem je chyba nebo je výsledkem cokoli kromě skupiny metod, vytvoří se chyba a neprovedou se žádné další kroky.- Rozlišení přetížení se provádí ve skupině metod s prázdným seznamem argumentů. Pokud výsledkem řešení přetížení nejsou žádné použitelné metody, vede k nejednoznačnosti nebo vede k jediné nejlepší metodě, ale tato metoda je buď statická nebo není veřejná, nebo její návratový typ není
bool
, vytvoří se chyba a neprovedou se žádné další kroky.- Typ kolekce je
X
, typ výčtu jeE
a typ elementu je typ vlastnostiCurrent
.V opačném případě se vytvoří chyba a neprovedou se žádné další kroky.
U await foreach
jsou pravidla podobně upravena. Jedinou změnou, která je nutná pro tuto specifikaci, je odebrání Extension methods do not contribute.
řádku z popisu, protože zbytek této specifikace je založen na výše uvedených pravidlech s různými názvy nahrazenými metodami vzoru.
Nevýhody
Každá změna přidává do jazyka další složitost a potenciálně umožňuje, aby věci, které nebyly navrženy k foreach
ani foreach
, jako například Range
, mohly být takto použity.
Alternativy
Nic nedělám.
Nevyřešené otázky
V tuto chvíli žádné.
C# feature specifications