GetEnumeratorCompatibilidad con la extensión para los foreach bucles.Extension GetEnumerator support for foreach loops.

ResumenSummary

Permite que los bucles foreach reconozcan un método GetEnumerator del método de extensión que, de otro modo, satisface el patrón foreach y se recorre la expresión cuando, de lo contrario, es un error.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.

MotivaciónMotivation

Esto hará que foreach esté alineado con cómo se implementan otras características de C#, incluida la desconstrucción asincrónica y basada en patrones.This will bring foreach inline with how other features in C# are implemented, including async and pattern-based deconstruction.

Diseño detalladoDetailed design

El cambio de especificación es relativamente sencillo.The spec change is relatively straightforward. Modificamos The foreach statement la sección de este texto:We modify The foreach statement section to this text:

El procesamiento en tiempo de compilación de una instrucción foreach primero determina el tipo de colección _, el tipo de _enumerador_ y el tipo de elemento de la expresión.The compile-time processing of a foreach statement first determines the collection type _, _enumerator type_ and _ element type of the expression. Esta determinación se realiza de la siguiente manera:This determination proceeds as follows:

  • Si el tipo X de expresión es un tipo de matriz, hay una conversión de referencia implícita de X a la IEnumerable interfaz (puesto que System.Array implementa esta interfaz).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). * El tipo de colección _ es la IEnumerable interfaz, el tipo de enumerador es la IEnumerator interfaz y el tipo de elemento _ * es el tipo de elemento del tipo de matriz 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.

  • Si el tipo X de expresión es dynamic , hay una conversión implícita de la expresión a la IEnumerable interfaz (conversiones dinámicas implícitas).If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). * El tipo de colección _ es la IEnumerable interfaz y el tipo de enumerador es la IEnumerator interfaz.The collection type _ is the IEnumerable interface and the _enumerator type*_ is the IEnumerator interface. Si el var identificador se proporciona como _local_variable_type *, el tipo de elemento es dynamic , de lo contrario, es object .If the var identifier is given as the _local_variable_type* then the element type is dynamic, otherwise it is object.

  • De lo contrario, determine si el tipo X tiene un GetEnumerator método adecuado:Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • Realiza la búsqueda de miembros en el tipo X con el identificador GetEnumerator y ningún argumento de tipo.Perform member lookup on the type X with identifier GetEnumerator and no type arguments. Si la búsqueda de miembros no produce una coincidencia, o produce una ambigüedad, o produce una coincidencia que no es un grupo de métodos, busque una interfaz enumerable como se describe a continuación.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. Se recomienda emitir una advertencia si la búsqueda de miembros produce cualquier cosa, excepto un grupo de métodos o ninguna coincidencia.It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • Realizar la resolución de sobrecarga utilizando el grupo de métodos resultante y una lista de argumentos vacía.Perform overload resolution using the resulting method group and an empty argument list. Si la resolución de sobrecarga da como resultado ningún método aplicable, da como resultado una ambigüedad o tiene como resultado un único método mejor pero ese método es estático o no público, busque una interfaz enumerable como se describe a continuación.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. Se recomienda emitir una advertencia si la resolución de sobrecarga produce todo excepto un método de instancia pública inequívoco o ningún método aplicable.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • Si el tipo de valor devuelto E del GetEnumerator método no es una clase, una estructura o un tipo de interfaz, se genera un error y no se realiza ningún otro paso.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 búsqueda de miembros se realiza en E con el identificador Current y sin argumentos de tipo.Member lookup is performed on E with the identifier Current and no type arguments. Si la búsqueda de miembros no produce ninguna coincidencia, el resultado es un error o el resultado es cualquier cosa excepto una propiedad de instancia pública que permita la lectura, se genera un error y no se realiza ningún paso más.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 búsqueda de miembros se realiza en E con el identificador MoveNext y sin argumentos de tipo.Member lookup is performed on E with the identifier MoveNext and no type arguments. Si la búsqueda de miembros no produce ninguna coincidencia, el resultado es un error o el resultado es cualquier cosa excepto un grupo de métodos, se genera un error y no se realiza ningún paso más.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 resolución de sobrecarga se realiza en el grupo de métodos con una lista de argumentos vacía.Overload resolution is performed on the method group with an empty argument list. Si la resolución de sobrecarga da como resultado ningún método aplicable, da como resultado una ambigüedad o tiene como resultado un único método mejor pero ese método es estático o no público, o su tipo de valor devuelto no es bool , se genera un error y no se realiza ningún otro paso.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.
    • El tipo de colección* es X , el tipo de enumerador es E y el tipo de elemento _ * es el tipo de la Current propiedad.The collection type _ is X, the _enumerator type_ is E, and the _ element type is the type of the Current property.
  • De lo contrario, compruebe si hay una interfaz enumerable:Otherwise, check for an enumerable interface:

    • Si entre todos los tipos Ti para los que hay una conversión implícita de X a IEnumerable<Ti> , hay un tipo único T , de modo que T no es dynamic y para todos los demás Ti hay una conversión implícita de IEnumerable<T> a IEnumerable<Ti> , entonces el tipo de colección _ es la interfaz IEnumerable<T> , el tipo de _enumerador*_ es la interfaz IEnumerator<T> y el tipo de elemento _ * es 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.
    • De lo contrario, si hay más de un tipo de este tipo T , se genera un error y no se realiza ningún paso más.Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • De lo contrario, si hay una conversión implícita de X en la System.Collections.IEnumerable interfaz, el tipo de colección* _ es esta interfaz, el tipo de enumerador es la interfaz System.Collections.IEnumerator y el tipo de elemento _ * es 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.
  • De lo contrario, determine si el tipo ' X ' tiene un GetEnumerator método de extensión adecuado:Otherwise, determine whether the type 'X' has an appropriate GetEnumerator extension method:

    • Realice la búsqueda de métodos de extensión en el tipo X con el identificador GetEnumerator .Perform extension method lookup on the type X with identifier GetEnumerator. Si la búsqueda de miembros no produce una coincidencia, o produce una ambigüedad, o produce una coincidencia que no es un grupo de métodos, se genera un error y no se realiza ningún paso más.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. Se recomienda que se produzcan problemas si la búsqueda de miembros produce cualquier cosa, excepto un grupo de métodos o ninguna coincidencia.It is recommended that a warning be issues if member lookup produces anything except a method group or no match.
    • Realice la resolución de sobrecarga utilizando el grupo de métodos resultante y un único argumento de tipo X .Perform overload resolution using the resulting method group and a single argument of type X. Si la resolución de sobrecargas no produce ningún método aplicable, da como resultado una ambigüedad o tiene como resultado un único método mejor, pero no se puede tener acceso a ese método, se genera un error que indica que no se realiza ningún paso más.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.
      • Esta resolución permite pasar el primer argumento por referencia si X es un tipo de estructura y el tipo de referencia es in .This resolution permits the first argument to be passed by ref if X is a struct type, and the ref kind is in.
    • Si el tipo de valor devuelto E del GetEnumerator método no es una clase, una estructura o un tipo de interfaz, se genera un error y no se realiza ningún otro paso.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 búsqueda de miembros se realiza en E con el identificador Current y sin argumentos de tipo.Member lookup is performed on E with the identifier Current and no type arguments. Si la búsqueda de miembros no produce ninguna coincidencia, el resultado es un error o el resultado es cualquier cosa excepto una propiedad de instancia pública que permita la lectura, se genera un error y no se realiza ningún paso más.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 búsqueda de miembros se realiza en E con el identificador MoveNext y sin argumentos de tipo.Member lookup is performed on E with the identifier MoveNext and no type arguments. Si la búsqueda de miembros no produce ninguna coincidencia, el resultado es un error o el resultado es cualquier cosa excepto un grupo de métodos, se genera un error y no se realiza ningún paso más.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 resolución de sobrecarga se realiza en el grupo de métodos con una lista de argumentos vacía.Overload resolution is performed on the method group with an empty argument list. Si la resolución de sobrecarga da como resultado ningún método aplicable, da como resultado una ambigüedad o tiene como resultado un único método mejor pero ese método es estático o no público, o su tipo de valor devuelto no es bool , se genera un error y no se realiza ningún otro paso.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.
    • El tipo de colección* es X , el tipo de enumerador es E y el tipo de elemento _ * es el tipo de la Current propiedad.The collection type _ is X, the _enumerator type_ is E, and the _ element type is the type of the Current property.
  • De lo contrario, se genera un error y no se realiza ningún paso más.Otherwise, an error is produced and no further steps are taken.

En await foreach el caso de, las reglas se modifican de forma similar.For await foreach, the rules are similarly modified. El único cambio necesario para esa especificación es quitar la Extension methods do not contribute. línea de la descripción, ya que el resto de esa especificación se basa en las reglas anteriores con nombres diferentes sustituidos por los métodos de patrón.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.

InconvenientesDrawbacks

Cada cambio agrega complejidad adicional al lenguaje y esto permite potencialmente cosas que no se diseñaron para ser Ed foreach foreach , como 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.

AlternativasAlternatives

No hacer nada.Doing nothing.

Preguntas no resueltasUnresolved questions

Ninguno en este momento.None at this point.