GetEnumeratorSupporto dell'estensione per i foreach cicli.Extension GetEnumerator support for foreach loops.

RiepilogoSummary

Consentire ai cicli foreach di riconoscere un metodo di estensione GetEnumerator che altrimenti soddisfa il modello foreach ed eseguire il ciclo sull'espressione quando sarebbe altrimenti un errore.Allow foreach loops to recognize an extension method GetEnumerator method that otherwise satisfies the foreach pattern, and loop over the expression when it would otherwise be an error.

MotivazioneMotivation

In questo modo, foreach inline verrà implementato come altre funzionalità in C#, tra cui la decostruzione asincrona e basata su modelli.This will bring foreach inline with how other features in C# are implemented, including async and pattern-based deconstruction.

Progettazione dettagliataDetailed design

La modifica delle specifiche è relativamente semplice.The spec change is relatively straightforward. The foreach statementLa sezione viene modificata in questo testo:We modify The foreach statement section to this text:

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.The compile-time processing of a foreach statement first determines the collection type _, _enumerator type* and _ element type* of the expression. Questa determinazione procede come segue:This determination proceeds as follows:

  • Se il tipo X di espressione è un tipo di matrice, esiste una conversione implicita del riferimento da X all' IEnumerable interfaccia (poiché System.Array implementa questa interfaccia).If the type X of expression is an array type then there is an implicit reference conversion from X to the IEnumerable interface (since System.Array implements this interface). Il tipo di raccolta* è l' IEnumerable interfaccia, il tipo di enumeratore è l' IEnumerator interfaccia e il tipo di elemento* è il tipo di elemento del tipo di matrice X .The collection type _ is the IEnumerable interface, the _enumerator type_ is the IEnumerator interface and the _ element type is the element type of the array type X.

  • Se il tipo X di espressione è, dynamic esiste una conversione implicita dall' espressione all' IEnumerable interfaccia (conversioni dinamiche implicite).If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). Il tipo di raccolta* è l' IEnumerable interfaccia e il tipo di enumeratore è l' IEnumerator interfaccia.The collection type _ is the IEnumerable interface and the _enumerator type*_ is the IEnumerator interface. Se l' var identificatore viene specificato come _local_variable_type *, il tipo di elemento è dynamic ; in caso contrario, è object .If the var identifier is given as the _local_variable_type* then the element type is dynamic, otherwise it is object.

  • In caso contrario, determinare se il tipo X dispone di un GetEnumerator metodo appropriato:Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • Eseguire la ricerca di membri sul tipo X con identificatore GetEnumerator e nessun argomento di tipo.Perform member lookup on the type X with identifier GetEnumerator and no type arguments. Se la ricerca dei membri non produce una corrispondenza o produce un'ambiguità o produce una corrispondenza che non è un gruppo di metodi, verificare la presenza di un'interfaccia enumerabile come descritto di seguito.If the member lookup does not produce a match, or it produces an ambiguity, or produces a match that is not a method group, check for an enumerable interface as described below. Si consiglia di emettere un avviso se la ricerca di membri produce qualsiasi elemento tranne un gruppo di metodi o nessuna corrispondenza.It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • Eseguire la risoluzione dell'overload usando il gruppo di metodi risultante e un elenco di argomenti vuoto.Perform overload resolution using the resulting method group and an empty argument list. Se la risoluzione dell'overload non produce metodi applicabili, comporta un'ambiguità o produce un unico metodo migliore, ma tale metodo è statico o non pubblico, verificare la presenza di un'interfaccia enumerabile come descritto di seguito.If overload resolution results in no applicable methods, results in an ambiguity, or results in a single best method but that method is either static or not public, check for an enumerable interface as described below. Si consiglia di emettere un avviso se la risoluzione dell'overload produce qualsiasi elemento tranne un metodo di istanza pubblica non ambiguo o senza metodi applicabili.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • Se il tipo restituito E del GetEnumerator metodo non è una classe, uno struct o un tipo di interfaccia, viene generato un errore e non vengono eseguiti altri passaggi.If the return type E of the GetEnumerator method is not a class, struct or interface type, an error is produced and no further steps are taken.
    • La ricerca del membro viene eseguita E con l'identificatore Current e nessun argomento di tipo.Member lookup is performed on E with the identifier Current and no type arguments. Se la ricerca dei membri non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi eccezione, ad eccezione di una proprietà di istanza pubblica che consente la lettura, viene generato un errore e non vengono eseguiti altri passaggi.If the member lookup produces no match, the result is an error, or the result is anything except a public instance property that permits reading, an error is produced and no further steps are taken.
    • La ricerca del membro viene eseguita E con l'identificatore MoveNext e nessun argomento di tipo.Member lookup is performed on E with the identifier MoveNext and no type arguments. Se la ricerca dei membri non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi eccezione a un gruppo di metodi, viene generato un errore e non vengono eseguiti altri passaggi.If the member lookup produces no match, the result is an error, or the result is anything except a method group, an error is produced and no further steps are taken.
    • La risoluzione dell'overload viene eseguita sul gruppo di metodi con un elenco di argomenti vuoto.Overload resolution is performed on the method group with an empty argument list. Se la risoluzione dell'overload non produce metodi applicabili, comporta un'ambiguità o produce un unico metodo migliore, ma tale metodo è statico o non pubblico oppure il tipo restituito non lo è bool , viene generato un errore e non vengono eseguiti altri passaggi.If overload resolution results in no applicable methods, results in an ambiguity, or results in a single best method but that method is either static or not public, or its return type is not bool, an error is produced and no further steps are taken.
    • Il tipo di raccolta* è X , il tipo di enumeratore è E e il tipo di elemento* è il tipo della Current Proprietà.The collection type _ is X, the _enumerator type_ is E, and the _ element type is the type of the Current property.
  • In caso contrario, verificare la presenza di un'interfaccia enumerabile:Otherwise, check for an enumerable interface:

    • Se tra tutti i tipi Ti per i quali esiste una conversione implicita da X a IEnumerable<Ti> , esiste un tipo univoco T che T non è dynamic e per tutti gli altri esiste una Ti conversione implicita da IEnumerable<T> a IEnumerable<Ti> , quindi il tipo di raccolta* è l'interfaccia IEnumerable<T> , il tipo di enumeratore è l'interfaccia IEnumerator<T> e il tipo di elemento* è T .If among all the types Ti for which there is an implicit conversion from X to IEnumerable<Ti>, there is a unique type T such that T is not dynamic and for all the other Ti there is an implicit conversion from IEnumerable<T> to IEnumerable<Ti>, then the collection type _ is the interface IEnumerable<T>, the _enumerator type_ is the interface IEnumerator<T>, and the _ element type is T.
    • In caso contrario, se è presente più di un tipo di questo tipo T , viene generato un errore e non vengono eseguiti altri passaggi.Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • In caso contrario, se esiste una conversione implicita da X all' System.Collections.IEnumerable interfaccia, il tipo di raccolta* è questa interfaccia, il tipo di enumeratore è l'interfaccia System.Collections.IEnumerator e il tipo di elemento _ * è object .Otherwise, if there is an implicit conversion from X to the System.Collections.IEnumerable interface, then the collection type _ is this interface, the _enumerator type_ is the interface System.Collections.IEnumerator, and the _ element type is object.
  • In caso contrario, determinare se il tipo ' X ' ha un GetEnumerator metodo di estensione appropriato:Otherwise, determine whether the type 'X' has an appropriate GetEnumerator extension method:

    • Eseguire la ricerca del metodo di estensione sul tipo X con l'identificatore GetEnumerator .Perform extension method lookup on the type X with identifier GetEnumerator. Se la ricerca dei membri 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.If the member lookup does not produce a match, or it produces an ambiguity, or produces a match which is not a method group, an error is produced and no further steps are taken. Si consiglia di generare un avviso se la ricerca dei membri produce qualsiasi elemento tranne un gruppo di metodi o nessuna corrispondenza.It is recommended that a warning be issues if member lookup produces anything except a method group or no match.
    • Eseguire la risoluzione dell'overload usando il gruppo di metodi risultante e un singolo argomento di tipo X .Perform overload resolution using the resulting method group and a single argument of type X. Se la risoluzione dell'overload non produce metodi applicabili, genera un'ambiguità o genera un solo metodo migliore, ma tale metodo non è accessibile, viene generato un errore senza ulteriori passaggi.If overload resolution produces no applicable methods, results in an ambiguity, or results in a single best method but that method is not accessible, an error is produced an no further steps are taken.
      • Questa risoluzione consente il passaggio del primo argomento tramite Ref se X è un tipo struct e il tipo di riferimento è in .This resolution permits the first argument to be passed by ref if X is a struct type, and the ref kind is in.
    • Se il tipo restituito E del GetEnumerator metodo non è una classe, uno struct o un tipo di interfaccia, viene generato un errore e non vengono eseguiti altri passaggi.If the return type E of the GetEnumerator method is not a class, struct or interface type, an error is produced and no further steps are taken.
    • La ricerca del membro viene eseguita E con l'identificatore Current e nessun argomento di tipo.Member lookup is performed on E with the identifier Current and no type arguments. Se la ricerca dei membri non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi eccezione, ad eccezione di una proprietà di istanza pubblica che consente la lettura, viene generato un errore e non vengono eseguiti altri passaggi.If the member lookup produces no match, the result is an error, or the result is anything except a public instance property that permits reading, an error is produced and no further steps are taken.
    • La ricerca del membro viene eseguita E con l'identificatore MoveNext e nessun argomento di tipo.Member lookup is performed on E with the identifier MoveNext and no type arguments. Se la ricerca dei membri non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi eccezione a un gruppo di metodi, viene generato un errore e non vengono eseguiti altri passaggi.If the member lookup produces no match, the result is an error, or the result is anything except a method group, an error is produced and no further steps are taken.
    • La risoluzione dell'overload viene eseguita sul gruppo di metodi con un elenco di argomenti vuoto.Overload resolution is performed on the method group with an empty argument list. Se la risoluzione dell'overload non produce metodi applicabili, comporta un'ambiguità o produce un unico metodo migliore, ma tale metodo è statico o non pubblico oppure il tipo restituito non lo è bool , viene generato un errore e non vengono eseguiti altri passaggi.If overload resolution results in no applicable methods, results in an ambiguity, or results in a single best method but that method is either static or not public, or its return type is not bool, an error is produced and no further steps are taken.
    • Il tipo di raccolta* è X , il tipo di enumeratore è E e il tipo di elemento* è il tipo della Current Proprietà.The collection type _ is X, the _enumerator type_ is E, and the _ element type is the type of the Current property.
  • In caso contrario, viene generato un errore e non vengono eseguiti altri passaggi.Otherwise, an error is produced and no further steps are taken.

Per await foreach , le regole vengono modificate in modo analogo.For await foreach, the rules are similarly modified. L'unica modifica necessaria a tale specifica è la rimozione della Extension methods do not contribute. riga dalla descrizione, poiché il resto di tale specifica è basato sulle regole precedenti con nomi diversi sostituiti dai metodi di pattern.The only change that is required to that spec is removing the Extension methods do not contribute. line from the description, as the rest of that spec is based on the above rules with different names substituted for the pattern methods.

SvantaggiDrawbacks

Ogni modifica aggiunge ulteriore complessità al linguaggio e questo potenzialmente consente a elementi che non sono stati progettati per essere foreach ed foreach , ad esempio Range .Every change adds additional complexity to the language, and this potentially allows things that weren't designed to be foreached to be foreached, like Range.

AlternativiAlternatives

Non eseguire alcuna operazione.Doing nothing.

Domande non risolteUnresolved questions

Nessuno a questo punto.None at this point.