Delen via


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 van X naar de IEnumerable-interface (omdat System.Array deze interface implementeert). Het verzamelingstype is de IEnumerable interface, het opsommingstype is de IEnumerator interface en het elementtype het elementtype is van het matrixtype X.

  • Als het type X van expressie is dynamic, is er een impliciete conversie van expressie naar de IEnumerable interface (§10.2.10). Het verzamelingstype is de IEnumerable interface en het enumeratortype is de IEnumerator interface. Als de var-identifier is gegeven als de local_variable_type, dan is het elementtypedynamic, anders is het object.

  • Als dat niet het geval is, moet u bepalen of het type X een geschikte GetEnumerator 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 methode GetEnumerator 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 identifier Current 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 identifier MoveNext 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 is E, en het elementtype is het type van de Current eigenschap.
  • Controleer anders of er een enumerable interface is:

    • Als er tussen alle typen Ti waarvoor een impliciete conversie van X naar IEnumerable<Ti>is, er een uniek type is T zodanig dat T niet dynamic is en voor alle andere Ti er een impliciete conversie van IEnumerable<T> naar IEnumerable<Ti>is, is het verzamelingstype de interface IEnumerable<T>, het enumeratortype is de interface IEnumerator<T>en het elementtype is T.
    • 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 de System.Collections.IEnumerable-interface is, is het verzamelingstype deze interface, het enumeratortype de interface System.Collections.IEnumeratoren het elementtype is object.
  • 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 referentietype inis.
    • Als het retourtype E van de methode GetEnumerator 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 identifier Current 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 identifier MoveNext 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 is E, en het elementtype is het type van de Current eigenschap.
  • Anders wordt een fout gegenereerd en worden er geen verdere stappen ondernomen.

Voor await foreachworden 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 foreachforeach, zoals Range.

Alternatieven

Niets doen.

Niet-opgeloste vragen

Geen op dit moment.