Extensie GetEnumerator
ondersteuning voor foreach
-lussen.
Notitie
Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.
Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de relevante LDM-notities (Language Design Meeting).
Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.
Probleem met de kampioen: https://github.com/dotnet/csharplang/issues/3194
Samenvatting
Sta foreach
-lussen toe om een extensiemethode GetEnumerator
te herkennen die normaal gesproken voldoet aan het foreach-patroon en over de expressie te lopen wanneer dit anders een fout zou zijn.
Motivatie
Hierdoor wordt foreach
inline gebracht met de wijze waarop andere functies in C# worden geïmplementeerd, waaronder asynchrone en op patronen gebaseerde deconstructie.
Gedetailleerd ontwerp
De specificatiewijziging is relatief eenvoudig. We wijzigen sectie The foreach statement
§13.9.5 naar deze tekst:
De compileertijdverwerking van een foreach-instructie bepaalt eerst het verzamelingstype, enumeratortype en elementtype van de expressie. Deze bepaling gaat als volgt:
Als het type
X
van expressie een matrixtype is, is er een impliciete verwijzingsconversie vanX
naar deIEnumerable
-interface (omdatSystem.Array
deze interface implementeert). Het verzamelingstype is deIEnumerable
interface, het opsommingstype is deIEnumerator
interface en het elementtype het elementtype is van het matrixtypeX
.Als het type
X
van expressie isdynamic
, is er een impliciete conversie van expressie naar deIEnumerable
interface (§10.2.10). Het verzamelingstype is deIEnumerable
interface en het enumeratortype is deIEnumerator
interface. Als devar
-identifier is gegeven als de local_variable_type, dan is het elementtypedynamic
, anders is hetobject
.Als dat niet het geval is, moet u bepalen of het type
X
een geschikteGetEnumerator
methode heeft:
- Voer lidzoekactie uit op het type
X
met id-GetEnumerator
en geen typeargumenten. Als de opzoekactie van het lid geen overeenkomst produceert, een dubbelzinnigheid oplevert, of een overeenkomst produceert die geen methodegroep is, controleert u, zoals hieronder beschreven, op een opsommingsbare interface. Het wordt aanbevolen een waarschuwing te afgegeven als lidzoekactie iets produceert behalve een methodegroep of geen overeenkomst.- Voer overbelastingsresolutie uit met behulp van de resulterende methodegroep en een lege lijst met argumenten. Als overbelastingsresolutie resulteert in geen toepasselijke methoden, resulteert in dubbelzinnigheid of resulteert in één beste methode, maar die methode is statisch of niet openbaar, controleert u op een opsommingsbare interface, zoals hieronder wordt beschreven. Het wordt aanbevolen een waarschuwing te afgegeven als overbelastingsresolutie iets produceert behalve een ondubbelzinnige methode voor openbare instanties of geen toepasselijke methoden.
- Als het retourtype
E
van de methodeGetEnumerator
geen klasse, struct of interfacetype is, wordt er een fout gegenereerd en worden er geen verdere stappen uitgevoerd.- Ledenopzoeking wordt uitgevoerd op
E
met de identifierCurrent
en zonder typeargumenten. Als de opzoekactie van het lid geen overeenkomst oplevert, is het resultaat een fout of is het resultaat iets behalve een eigenschap van een openbare instantie die het lezen toestaat, wordt er een fout gegenereerd en worden er geen verdere stappen ondernomen.- Ledenopzoeking wordt uitgevoerd op
E
met de identifierMoveNext
en zonder typeargumenten. Als de opzoekactie van het lid geen overeenkomst oplevert, of als het resultaat een fout is, of het resultaat is iets anders dan een methodegroep, dan wordt er een fout gegenereerd en worden er geen verdere stappen ondernomen.- Overbelastingsresolutie wordt uitgevoerd op de methodegroep met een lege lijst met argumenten. Als overbelastingsresolutie resulteert in geen toepasselijke methoden, resulteert dit in een dubbelzinnigheid of resulteert in één beste methode, maar die methode is statisch of niet openbaar, of het retourtype is niet
bool
, er wordt een fout gegenereerd en er worden geen verdere stappen uitgevoerd.- Het verzamelingstype is
X
, het opsommingstype isE
, en het elementtype is het type van deCurrent
eigenschap.Controleer anders of er een enumerable interface is:
- Als er tussen alle typen
Ti
waarvoor een impliciete conversie vanX
naarIEnumerable<Ti>
is, er een uniek type isT
zodanig datT
nietdynamic
is en voor alle andereTi
er een impliciete conversie vanIEnumerable<T>
naarIEnumerable<Ti>
is, is het verzamelingstype de interfaceIEnumerable<T>
, het enumeratortype is de interfaceIEnumerator<T>
en het elementtype isT
.- Anders, als er meer dan één dergelijk type is
T
, wordt er een fout geproduceerd en worden er geen verdere stappen ondernomen.- Als er anders een impliciete conversie van
X
naar deSystem.Collections.IEnumerable
-interface is, is het verzamelingstype deze interface, het enumeratortype de interfaceSystem.Collections.IEnumerator
en het elementtype isobject
.Als dat niet het geval is, moet u bepalen of het type X een geschikte
GetEnumerator
extensiemethode heeft:
- Zoek de extensiemethode op het type
X
met id-GetEnumerator
. Als de ledenzoekopdracht geen overeenkomst oplevert, een dubbelzinnigheid oplevert, of een overeenkomst oplevert die geen methodegroep is, dan wordt er een fout gegenereerd en worden er geen verdere stappen ondernomen. Het wordt aanbevolen om een waarschuwing uit te geven als een lidopzoekactie iets anders dan een methodegroep of geen overeenkomst oplevert.- Overbelastingsresolutie uitvoeren met behulp van de resulterende methodegroep en één argument van het type
X
. Als overbelastingsresolutie geen toepasselijke methoden produceert, een dubbelzinnigheid oplevert, of resulteert in één beste methode die niet toegankelijk is, wordt er een fout gegenereerd en worden er geen verdere stappen ondernomen.
- Met deze resolutie kan het eerste argument worden doorgegeven als referentie als
X
een structtype is en het referentietypein
is.- Als het retourtype
E
van de methodeGetEnumerator
geen klasse, struct of interfacetype is, wordt er een fout gegenereerd en worden er geen verdere stappen uitgevoerd.- Ledenopzoeking wordt uitgevoerd op
E
met de identifierCurrent
en zonder typeargumenten. Als de opzoekactie van het lid geen overeenkomst oplevert, is het resultaat een fout of is het resultaat iets behalve een eigenschap van een openbare instantie die het lezen toestaat, wordt er een fout gegenereerd en worden er geen verdere stappen ondernomen.- Ledenopzoeking wordt uitgevoerd op
E
met de identifierMoveNext
en zonder typeargumenten. Als de opzoekactie van het lid geen overeenkomst oplevert, of als het resultaat een fout is, of het resultaat is iets anders dan een methodegroep, dan wordt er een fout gegenereerd en worden er geen verdere stappen ondernomen.- Overbelastingsresolutie wordt uitgevoerd op de methodegroep met een lege lijst met argumenten. Als overbelastingsresolutie resulteert in geen toepasselijke methoden, resulteert dit in een dubbelzinnigheid of resulteert in één beste methode, maar die methode is statisch of niet openbaar, of het retourtype is niet
bool
, er wordt een fout gegenereerd en er worden geen verdere stappen uitgevoerd.- Het verzamelingstype is
X
, het opsommingstype isE
, en het elementtype is het type van deCurrent
eigenschap.Anders wordt een fout gegenereerd en worden er geen verdere stappen ondernomen.
Voor await foreach
worden de regels op dezelfde manier gewijzigd. De enige wijziging die vereist is voor die specificatie, is het verwijderen van de Extension methods do not contribute.
regel uit de beschrijving, omdat de rest van die specificatie is gebaseerd op de bovenstaande regels met verschillende namen die worden vervangen door de patroonmethoden.
Nadelen
Elke wijziging voegt extra complexiteit toe aan de taal en hierdoor kunnen mogelijk dingen die niet zijn ontworpen om te worden foreach
foreach
, zoals Range
.
Alternatieven
Niets doen.
Niet-opgeloste vragen
Geen op dit moment.
C# feature specifications