Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Supporto dell'estensione
Nota
Questo articolo è una specifica di funzionalità. La specifica funge da documento di progettazione per la funzionalità. Include le modifiche specifiche proposte, insieme alle informazioni necessarie durante la progettazione e lo sviluppo della funzionalità. Questi articoli vengono pubblicati fino a quando le modifiche specifiche proposte non vengono completate e incorporate nella specifica ECMA corrente.
Potrebbero verificarsi alcune discrepanze tra la specifica di funzionalità e l'implementazione completata. Tali differenze vengono acquisite nelle note
Ulteriori informazioni sul processo di adozione dei feature speclet nello standard della lingua C# sono disponibili nell'articolo sulle specifiche .
Problema del campione: https://github.com/dotnet/csharplang/issues/3194
Sommario
Consentire ai cicli foreach di riconoscere un metodo di estensione GetEnumerator che soddisfa il modello foreach e iterare sull'espressione quando altrimenti sarebbe un errore.
Motivazione
Ciò porterà foreach in linea con il modo in cui vengono implementate altre funzionalità in C#, tra cui la decostruzione asincrona e basata su modelli.
Progettazione dettagliata
La modifica delle specifiche è relativamente semplice. La sezione di
L'elaborazione in fase di compilazione di un'istruzione foreach determina innanzitutto il tipo di raccolta , il tipo di enumeratore e il tipo di elemento dell'espressione. Questa determinazione procede come segue:
Se il tipo
Xdell'espressione è un tipo di matrice, è presente una conversione implicita dei riferimenti daXall'interfacciaIEnumerable(poichéSystem.Arrayimplementa questa interfaccia). Il tipo di raccolta è l'interfacciaIEnumerable, il tipo di enumeratore è l'interfacciaIEnumeratore il tipo di elemento è il tipo di elemento del tipo di matriceX.Se il tipo
Xdell'espressione èdynamicviene eseguita una conversione implicita da expression all'interfacciaIEnumerable(§10.2.10). Il tipo di raccolta è l'interfacciaIEnumerablee il tipo di enumeratore è l'interfacciaIEnumerator. Se l'identificatorevarviene assegnato come local_variable_type, il tipo di elemento èdynamic, in caso contrario èobject.In caso contrario, determinare se il tipo
Xdispone di un metodo diGetEnumeratorappropriato:
- Eseguire la ricerca dei membri nel tipo
Xcon identificatoreGetEnumeratore senza argomenti di tipo. Se la ricerca del membro non produce una corrispondenza, o produce un'ambiguità, o produce una corrispondenza che non è un gruppo di metodi, verificate la presenza di un'interfaccia enumerabile come descritto di seguito. È consigliabile generare un avviso se la ricerca dei membri produce elementi tranne un gruppo di metodi o nessuna corrispondenza.- Eseguire la risoluzione dell'overload usando il gruppo di metodi risultante e un elenco di argomenti vuoto. Se la risoluzione dell'overload non produce metodi applicabili, genera un'ambiguità o restituisce un singolo metodo migliore, ma tale metodo è statico o non pubblico, verificare la presenza di un'interfaccia enumerabile come descritto di seguito. È consigliabile generare un avviso se la risoluzione dell'overload produce qualcosa di diverso da un metodo di istanza pubblica chiaro o nessun metodo che si possa applicare.
- Se il tipo restituito
Edel metodoGetEnumeratornon è una classe, uno struct o un tipo di interfaccia, viene generato un errore e non vengono eseguiti altri passaggi.- La ricerca dei membri viene eseguita su
Econ l'identificatoreCurrente senza argomenti di tipo. Se la ricerca del membro non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi elemento tranne una proprietà dell'istanza pubblica che consente la lettura, viene generato un errore e non vengono eseguiti altri passaggi.- La ricerca dei membri viene eseguita su
Econ l'identificatoreMoveNexte senza argomenti di tipo. Se la ricerca del membro non produce alcuna corrispondenza, il risultato è un errore o il risultato è qualsiasi elemento ad eccezione di un gruppo di metodi, viene generato un errore e non vengono eseguiti altri passaggi.- La risoluzione del sovraccarico viene eseguita sul gruppo di metodi con un elenco di parametri vuoto. Se la risoluzione dell'overload non restituisce metodi applicabili, genera un'ambiguità o restituisce un singolo metodo migliore, ma tale metodo è statico o non pubblico oppure il tipo restituito non è
bool, viene generato un errore e non vengono eseguiti altri passaggi.- Il tipo di raccolta è
X, il tipo di enumeratore èEe il tipo di elemento è il tipo della proprietàCurrent.In caso contrario, verificare la presenza di un'interfaccia enumerabile:
- Se tra tutti i tipi
Tiper cui è presente una conversione implicita daXaIEnumerable<Ti>, esiste un tipo univocoTin modo cheTnon siadynamice per tutte le altreTisia presente una conversione implicita daIEnumerable<T>aIEnumerable<Ti>, il tipo di raccolta è l'interfacciaIEnumerable<T>, il tipo di enumeratore è l'interfacciaIEnumerator<T>e il tipo di elemento èT.- In caso contrario, se è presente più di un tipo di questo tipo
T, viene generato un errore e non vengono eseguiti altri passaggi.- In caso contrario, se è presente una conversione implicita da
Xall'interfacciaSystem.Collections.IEnumerable, il tipo di raccolta è questa interfaccia, il tipo di enumeratore è l'interfacciaSystem.Collections.IEnumeratore il tipo di elemento èobject.In caso contrario, determinare se il tipo 'X' dispone di un metodo di estensione
GetEnumeratorappropriato:
- Eseguire la ricerca del metodo di estensione nel tipo
Xcon identificatoreGetEnumerator. Se la ricerca del membro non produce una corrispondenza o produce un'ambiguità o produce una corrispondenza che non è un gruppo di metodi, viene generato un errore e non vengono eseguiti altri passaggi. È consigliabile emettere un avviso se la ricerca dei membri produce qualcosa diverso da un gruppo di metodi o nessuna corrispondenza.- Esegui la risoluzione dell'overload utilizzando il gruppo di metodi risultante e un singolo argomento di tipo
X. Se la risoluzione dell'overload non produce metodi applicabili, genera un'ambiguità o restituisce un singolo metodo migliore, ma tale metodo non è accessibile, viene generato un errore senza ulteriori passaggi.
- Questa risoluzione consente di passare il primo argomento per ref se
Xè un tipo struct e il tipo ref èin.- Se il tipo restituito
Edel metodoGetEnumeratornon è una classe, uno struct o un tipo di interfaccia, viene generato un errore e non vengono eseguiti altri passaggi.- La ricerca dei membri viene eseguita su
Econ l'identificatoreCurrente senza argomenti di tipo. Se la ricerca del membro non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi elemento tranne una proprietà dell'istanza pubblica che consente la lettura, viene generato un errore e non vengono eseguiti altri passaggi.- La ricerca dei membri viene eseguita su
Econ l'identificatoreMoveNexte senza argomenti di tipo. Se la ricerca del membro non produce alcuna corrispondenza, il risultato è un errore o il risultato è qualsiasi elemento ad eccezione di un gruppo di metodi, viene generato un errore e non vengono eseguiti altri passaggi.- La risoluzione del sovraccarico viene eseguita sul gruppo di metodi con un elenco di parametri vuoto. Se la risoluzione dell'overload non restituisce metodi applicabili, genera un'ambiguità o restituisce un singolo metodo migliore, ma tale metodo è statico o non pubblico oppure il tipo restituito non è
bool, viene generato un errore e non vengono eseguiti altri passaggi.- Il tipo di raccolta è
X, il tipo di enumeratore èEe il tipo di elemento è il tipo della proprietàCurrent.In caso contrario, viene generato un errore e non vengono eseguiti altri passaggi.
Per await foreach, le regole vengono modificate in modo analogo. L'unica modifica richiesta a tale specifica è rimuovere la riga Extension methods do not contribute. dalla descrizione, poiché il resto di quella specifica si basa sulle regole sopra indicate con nomi diversi sostituiti ai metodi del pattern.
Svantaggi
Ogni modifica aggiunge complessità al linguaggio e potrebbe permettere agli elementi che non sono stati progettati per essere foreachdi essere foreach, ad esempio Range.
Alternative
Non fare nulla.
Domande non risolte
Nessuno a questo punto.
C# feature specifications