Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Obsługa
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ą ujęte w odpowiednich notatkach ze spotkania dotyczącego projektowania 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/3194
Streszczenie
Pozwól pętlom foreach rozpoznać metodę rozszerzającą GetEnumerator, która spełnia wzorzec foreach, i przetwarzać wyrażenie, gdy w innym przypadku wystąpiłby błąd.
Motywacja
Spowoduje to, że foreach będzie zgodny z tym, jak inne funkcje są implementowane w języku C#, w tym funkcje asynchroniczne i dekonstrukcję opartą na wzorcach.
Szczegółowy projekt
Zmiana specyfikacji jest stosunkowo prosta. Modyfikujemy sekcję The foreach statement§13.9.5 na następujący tekst:
Przetwarzanie instrukcji foreach w czasie kompilacji najpierw określa typ kolekcji , typ modułu wyliczającego oraz typ elementu wyrażenia. Ta determinacja jest przeprowadzana w następujący sposób:
Jeśli typ
Xwyrażenia jest typem tablicy, istnieje niejawna konwersja odwołania zXdo interfejsuIEnumerable(ponieważSystem.Arrayimplementuje ten interfejs). Typ kolekcji jest interfejsemIEnumerable, typem modułu wyliczającego jest interfejsIEnumerator, a typ elementu jest typem elementu typu tablicyX.Jeśli typ
Xwyrażenia jestdynamic, istnieje niejawna konwersja z wyrażenia do interfejsuIEnumerable(§10.2.10). Typ kolekcji to interfejsIEnumerable, a typem modułu wyliczającego jest interfejsIEnumerator. Jeśli identyfikatorvarjest podany jako local_variable_type, typ elementu jestdynamic, w przeciwnym razie jestobject.W przeciwnym razie określ, czy typ
Xma odpowiednią metodęGetEnumerator:
- Przeprowadź wyszukiwanie członków dla typu
Xz identyfikatoremGetEnumeratori bez argumentów typu. Jeśli wyszukiwanie członka nie daje dopasowania, powoduje niejednoznaczność lub zwraca dopasowanie, które nie jest zbiorem metod, sprawdź, czy istnieje interfejs wyliczalny zgodnie z poniższym opisem. Zaleca się, aby ostrzeżenie zostało wydane, jeśli wyszukiwanie elementu członkowskiego generuje cokolwiek oprócz grupy metod lub braku dopasowania.- Przeprowadź rozpoznawanie przeciążeń przy użyciu wynikowej grupy metod i pustej listy argumentów. Jeśli rozpoznawanie przeciążenia nie powoduje zastosowania metod, powoduje niejednoznaczność lub powoduje utworzenie jednej najlepszej metody, ale ta metoda jest statyczna lub nie jest publiczna, sprawdź interfejs wyliczalny, jak opisano poniżej. Zaleca się, aby ostrzeżenie zostało wydane, jeśli rozwiązanie przeciążenia produkuje coś innego niż jednoznaczną metodę instancji publicznej lub brak odpowiednich metod.
- Jeśli zwracany typ
EmetodyGetEnumeratornie jest klasą, strukturą ani typem interfejsu, zostanie wygenerowany błąd i nie zostaną wykonane żadne dalsze kroki.- Wyszukiwanie członków jest wykonywane na
Ebez argumentów typu z identyfikatoremCurrent. Jeśli wyszukiwanie elementu członkowskiego nie daje dopasowania, wynik jest błędem lub wynikiem jest wszystko, z wyjątkiem właściwości wystąpienia publicznego, która zezwala na odczyt, zostanie wygenerowany błąd i nie zostaną podjęte żadne dalsze kroki.- Wyszukiwanie członków jest wykonywane na
Ebez argumentów typu z identyfikatoremMoveNext. Jeśli wyszukiwanie członka nie daje dopasowania lub wynikiem jest coś poza grupą metod, generowany jest błąd i nie są wykonywane żadne dalsze kroki.- Rozpoznawanie przeciążenia jest wykonywane w grupie metod z pustą listą argumentów. Jeśli rozpoznawanie przeciążenia nie powoduje żadnych odpowiednich metod, powoduje niejednoznaczność lub powoduje utworzenie jednej najlepszej metody, ale ta metoda jest statyczna lub nie jest publiczna lub jej typ zwracany nie jest
bool, zostanie wygenerowany błąd i nie zostaną podjęte żadne dalsze kroki.- Typ kolekcji jest
X, typ modułu wyliczającego jestE, a typ elementu jest typem właściwościCurrent.W przeciwnym razie, sprawdź, czy dostępny jest interfejs wyliczalny.
- Jeśli wśród wszystkich typów
, dla których istnieje niejawna konwersja z na , istnieje unikatowy typ taki, że nie jest i dla wszystkich innych istnieje niejawna konwersja z na , wówczas typ kolekcji jest interfejsem , typ modułu wyliczającego to interfejs , a typ elementu jest . - W przeciwnym razie, jeśli istnieje więcej niż jeden taki typ
T, zostanie wygenerowany błąd i nie zostaną podjęte żadne dalsze kroki.- W przeciwnym razie, jeśli istnieje niejawna konwersja z
Xdo interfejsuSystem.Collections.IEnumerable, to typ kolekcji jest tym interfejsem, typ wyliczający jest interfejsemSystem.Collections.IEnumerator, a typ elementu jestobject.W przeciwnym razie określ, czy typ "X" ma odpowiednią metodę rozszerzenia
GetEnumerator:
- Przeprowadź wyszukiwanie metody rozszerzenia dla typu
Xz identyfikatoremGetEnumerator. Jeśli wyszukiwanie członka nie daje dopasowania, generuje niejednoznaczność lub generuje dopasowanie, które nie jest grupą metod, występuje błąd i nie są podejmowane żadne dalsze kroki. Zaleca się, aby należy wydać ostrzeżenie, jeśli wyszukiwanie elementów członkowskich generuje coś innego, niż grupa metod lub brak dopasowania.- Przeprowadź rozpoznawanie przeciążeń przy użyciu wynikowej grupy metod i pojedynczego argumentu typu
X. Jeśli rozpoznawanie przeciążenia nie generuje żadnych odpowiednich metod, powoduje niejednoznaczność lub powoduje utworzenie jednej najlepszej metody, ale ta metoda nie jest dostępna, zostanie wygenerowany błąd, nie zostaną wykonane żadne dalsze kroki.
- To rozwiązanie zezwala na przekazanie pierwszego argumentu przez referencję, jeśli
Xjest typem struktury, a rodzaj referencji jestin.- Jeśli zwracany typ
EmetodyGetEnumeratornie jest klasą, strukturą ani typem interfejsu, zostanie wygenerowany błąd i nie zostaną wykonane żadne dalsze kroki.- Wyszukiwanie członków jest wykonywane na
Ebez argumentów typu z identyfikatoremCurrent. Jeśli wyszukiwanie elementu członkowskiego nie daje dopasowania, wynik jest błędem lub wynikiem jest wszystko, z wyjątkiem właściwości wystąpienia publicznego, która zezwala na odczyt, zostanie wygenerowany błąd i nie zostaną podjęte żadne dalsze kroki.- Wyszukiwanie członków jest wykonywane na
Ebez argumentów typu z identyfikatoremMoveNext. Jeśli wyszukiwanie członka nie daje dopasowania lub wynikiem jest coś poza grupą metod, generowany jest błąd i nie są wykonywane żadne dalsze kroki.- Rozpoznawanie przeciążenia jest wykonywane w grupie metod z pustą listą argumentów. Jeśli rozpoznawanie przeciążenia nie powoduje żadnych odpowiednich metod, powoduje niejednoznaczność lub powoduje utworzenie jednej najlepszej metody, ale ta metoda jest statyczna lub nie jest publiczna lub jej typ zwracany nie jest
bool, zostanie wygenerowany błąd i nie zostaną podjęte żadne dalsze kroki.- Typ kolekcji jest
X, typ modułu wyliczającego jestE, a typ elementu jest typem właściwościCurrent.W przeciwnym razie zostanie wygenerowany błąd i nie zostaną podjęte żadne dalsze kroki.
W przypadku await foreachreguły są podobnie modyfikowane. Jedyną zmianą wymaganą do tej specyfikacji jest usunięcie wiersza Extension methods do not contribute. z opisu, ponieważ reszta tej specyfikacji jest oparta na powyższych regułach o różnych nazwach zastąpionych metodami wzorca.
Wady i niedogodności
Każda zmiana zwiększa złożoność języka i potencjalnie pozwala, aby elementy, które nie zostały zaprojektowane do foreach, były foreach, takie jak Range.
Alternatywy
Nic nie robi.
Nierozwiązane pytania
Nic w tym momencie.
C# feature specifications