Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Tillägg av stöd för
Not
Den här artikeln är en funktionsspecifikation. Specifikationen fungerar som designdokument för funktionen. Den innehåller föreslagna specifikationsändringar, tillsammans med information som behövs under utformningen och utvecklingen av funktionen. Dessa artiklar publiceras tills de föreslagna specifikationsändringarna har slutförts och införlivats i den aktuella ECMA-specifikationen.
Det kan finnas vissa skillnader mellan funktionsspecifikationen och den slutförda implementeringen. Dessa skillnader samlas in i de relevanta LDM-anteckningar (Language Design Meeting).
Du kan läsa mer om processen för att införa funktionsspecifikationer i C#-språkstandarden i artikeln om specifikationerna.
Champion-fråga: https://github.com/dotnet/csharplang/issues/3194
Sammanfattning
Tillåt foreach-loopar att identifiera en tilläggsmetod GetEnumerator metod som annars uppfyller foreach-mönstret och loopa över uttrycket när det annars skulle vara ett fel.
Motivation
Detta kommer att göra foreach i linje med hur andra funktioner i C# implementeras, inklusive asynkrona och mönsterbaserade dekonstruktioner.
Detaljerad design
Specifikationsändringen är relativt enkel. Vi ändrar The foreach statement§13.9.5 avsnitt till denna text:
Kompileringstidsbearbetningen av en foreach-instruktion avgör först samlingstyp, uppräkningstyp och elementtyp för uttrycket. Den här bedömningen fortsätter på följande sätt:
Om typen
Xav uttryck är en matristyp finns det en implicit referenskonvertering frånXtillIEnumerable-gränssnittet (eftersomSystem.Arrayimplementerar det här gränssnittet). Den samlingstypen ärIEnumerable-gränssnittet, uppräkningstyp ärIEnumerator-gränssnittet och -elementtypen är elementtypen för matristypenX.
Om typen
Xav uttryck ärdynamicsker en implicit konvertering från uttryck till gränssnittetIEnumerable(§10.2.10). Den samlingstypen ärIEnumerable-gränssnittet och uppräkningstyp ärIEnumerator-gränssnittet. Om identifierarenvaranges som lokal_variabeltyp , är elementtypendynamic, annars är denobject.
I annat fall avgör du om typen
Xhar en lämpligGetEnumeratormetod:
- Utför medlemssökning på typen
Xmed identifierarenGetEnumeratoroch inga typargument. Om medlemssökningen inte ger någon matchning, eller om den skapar en tvetydighet eller skapar en matchning som inte är en metodgrupp, kontrollerar du om det finns ett uppräkningsbart gränssnitt enligt beskrivningen nedan. Vi rekommenderar att en varning utfärdas om medlemssökningen genererar något annat än en metodgrupp eller ingen matchning.- Utför överbelastningsmatchning med hjälp av den resulterande metodgruppen och en tom argumentlista. Om överbelastningsmatchning inte resulterar i några tillämpliga metoder, resulterar i en tvetydighet eller resulterar i en enda bästa metod, men den metoden antingen är statisk eller inte offentlig, kontrollerar du om det finns ett uppräkningsbart gränssnitt enligt beskrivningen nedan. Vi rekommenderar att en varning utfärdas ifall överbelastningsupplösning ger något annat än en entydig offentlig instansmetod eller inga metoder är tillämpliga.
- Om returtypen
Eav metodenGetEnumeratorinte är en klass-, struct- eller gränssnittstyp genereras ett fel och inga ytterligare steg vidtas.- Medlemssökning utförs på
Emed identifierarenCurrentoch inga typargument. Om medlemssökningen inte ger någon matchning är resultatet ett fel eller resultatet är något annat än en offentlig instansegenskap som tillåter läsning, ett fel skapas och inga ytterligare åtgärder vidtas.- Medlemssökning utförs på
Emed identifierarenMoveNextoch inga typargument. Om medlemssökningen inte ger någon matchning är resultatet ett fel, eller resultatet är något annat än en metodgrupp, ett fel genereras och inga ytterligare åtgärder vidtas.- Överbelastningslösning utförs på metodgruppen med en tom argumentlista. Om överbelastningsmatchning inte resulterar i några tillämpliga metoder, resulterar i en tvetydighet eller resulterar i en enda bästa metod, men den metoden är antingen statisk eller inte offentlig, eller dess returtyp är inte
boolgenereras ett fel och inga ytterligare åtgärder vidtas.- Den samlingstypen är
X, uppräkningstypen ärEoch -elementtypen är typen av egenskap förCurrent.
Annars kontrollerar du om det finns ett uppräkningsbart gränssnitt:
- Om det bland alla typer
Tiför vilka det finns en implicit konvertering frånXtillIEnumerable<Ti>finns det en unik typTså attTintedynamicoch för alla andraTifinns det en implicit konvertering frånIEnumerable<T>tillIEnumerable<Ti>, är samlingstyp gränssnittetIEnumerable<T>, uppräkningstyp är gränssnittetIEnumerator<T>och elementtypen ärT.- Om det finns fler än en sådan typ
Tgenereras annars ett fel och inga ytterligare åtgärder vidtas.- Om det annars finns en implicit konvertering från
XtillSystem.Collections.IEnumerable-gränssnittet är -samlingstypen det här gränssnittet uppräkningstypen gränssnittetSystem.Collections.IEnumeratoroch -elementtypen ärobject.
I annat fall avgör du om typen "X" har en lämplig
GetEnumeratortilläggsmetod:
- Utför tilläggsmetodsökning på typen
Xmed identifierarenGetEnumerator. Om medlemssökningen inte genererar någon matchning, eller om den skapar en tvetydighet, eller skapar en matchning som inte är en metodgrupp, genereras ett fel och inga ytterligare åtgärder vidtas. Vi rekommenderar att en varning utfärdas om medlemssökningen genererar något annat än en metodgrupp eller ingen träff.- Utför överbelastningsmatchning med hjälp av den resulterande metodgruppen och ett enda argument av typen
X. Om överbelastningsmatchning inte ger några tillämpliga metoder, resulterar i en tvetydighet eller resulterar i en enda bästa metod, men den metoden inte är tillgänglig, genereras ett fel utan ytterligare åtgärder.
- Den här lösningen tillåter att det första argumentet skickas av referens om
Xär en structtyp och referenstypen ärin.- Om returtypen
Eav metodenGetEnumeratorinte är en klass-, struct- eller gränssnittstyp genereras ett fel och inga ytterligare steg vidtas.- Medlemssökning utförs på
Emed identifierarenCurrentoch inga typargument. Om medlemssökningen inte ger någon matchning är resultatet ett fel eller resultatet är något annat än en offentlig instansegenskap som tillåter läsning, ett fel skapas och inga ytterligare åtgärder vidtas.- Medlemssökning utförs på
Emed identifierarenMoveNextoch inga typargument. Om medlemssökningen inte ger någon matchning är resultatet ett fel, eller resultatet är något annat än en metodgrupp, ett fel genereras och inga ytterligare åtgärder vidtas.- Överbelastningslösning utförs på metodgruppen med en tom argumentlista. Om överbelastningsmatchning inte resulterar i några tillämpliga metoder, resulterar i en tvetydighet eller resulterar i en enda bästa metod, men den metoden är antingen statisk eller inte offentlig, eller dess returtyp är inte
boolgenereras ett fel och inga ytterligare åtgärder vidtas.- Den samlingstypen är
X, uppräkningstypen ärEoch -elementtypen är typen av egenskap förCurrent.
Annars genereras ett fel och inga ytterligare åtgärder vidtas.
För await foreachändras reglerna på liknande sätt. Den enda ändring som krävs för den specifikationen är att ta bort den Extension methods do not contribute. raden från beskrivningen, eftersom resten av specifikationen baseras på ovanstående regler med olika namn som ersätts med mönstermetoderna.
Nackdelar
Varje ändring lägger till ytterligare komplexitet i språket, vilket kan leda till att saker som inte är utformade för att foreached kan bli foreached, som Range.
Alternativ
Gör ingenting.
Olösta frågor
Ingen just nu.
C# feature specifications