Sdílet prostřednictvím


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 z X na rozhraní IEnumerable (protože System.Array implementuje toto rozhraní). typ kolekce je IEnumerable rozhraní, typ enumerátoru je IEnumerator rozhraní a typ elementu je typ prvku typu pole X.

  • Pokud je typ X výrazu dynamic pak existuje implicitní převod z výrazu na rozhraní IEnumerable (§10.2.10). Typ kolekce je rozhraní a typ enumerátoru je rozhraní . Pokud je identifikátor uveden jako lokální_typ_proměnné, pak typ prvku je , jinak je .

  • V opačném případě určete, zda typ X má odpovídající metodu GetEnumerator:

    • Proveďte vyhledávání členů u typu X s identifikátorem GetEnumerator 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 metody GetEnumerator 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átorem Current 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átorem MoveNext 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 je Ea typ elementu je typ vlastnosti Current.
  • 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 z X na IEnumerable<Ti>, existuje jedinečný typ T takový, že T není dynamic a pro všechny ostatní Ti existuje implicitní převod z IEnumerable<T> na IEnumerable<Ti>, pak typ kolekce je rozhraní IEnumerable<T>, , typ enumerátoru je IEnumerator<T>rozhraní a typ prvku je T.
    • 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átoru System.Collections.IEnumerator je rozhraní a typ prvku object 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átorem GetEnumerator. 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 je in.
    • Pokud návratový typ E metody GetEnumerator 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átorem Current 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átorem MoveNext 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 je Ea typ elementu je typ vlastnosti Current.
  • V opačném případě se vytvoří chyba a neprovedou se žádné další kroky.

U await foreachjsou 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 foreachani 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é.