¿Cuál es el tipo de hormigón para este IEnumerable<string>
?¿Qué tipo de hormigón devuelve 'rendimiento rendimiento'?
private IEnumerable<string> GetIEnumerable()
{
yield return "a";
yield return "a";
yield return "a";
}
¿Cuál es el tipo de hormigón para este IEnumerable<string>
?¿Qué tipo de hormigón devuelve 'rendimiento rendimiento'?
private IEnumerable<string> GetIEnumerable()
{
yield return "a";
yield return "a";
yield return "a";
}
Es un tipo de compilador generado. El compilador genera una implementación IEnumerator<string>
que devuelve tres valores "a" y una clase de esqueleto IEnumerable<string>
que proporciona uno de estos en su método GetEnumerator
.
El código generado se ve algo como esto *:
// No idea what the naming convention for the generated class is --
// this is really just a shot in the dark.
class GetIEnumerable_Enumerator : IEnumerator<string>
{
int _state;
string _current;
public bool MoveNext()
{
switch (_state++)
{
case 0:
_current = "a";
break;
case 1:
_current = "a";
break;
case 2:
_current = "a";
break;
default:
return false;
}
return true;
}
public string Current
{
get { return _current; }
}
object IEnumerator.Current
{
get { return Current; }
}
void IEnumerator.Reset()
{
// not sure about this one -- never really tried it...
// I'll just guess
_state = 0;
_current = null;
}
}
class GetIEnumerable_Enumerable : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
return new GetIEnumerable_Enumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
O tal vez, como dice SLaks en su respuesta, las dos implementaciones terminan en la misma clase. Escribí esto basado en mi memoria entrecortada del código generado que había visto antes; realmente, una clase sería suficiente, ya que no hay razón para que la funcionalidad anterior requiera dos.
De hecho, ahora que lo pienso de ella, las dos implementaciones realmente deben caen dentro de una sola clase, como acabo de recordar las funciones que utilizan yield
declaraciones deben tener un tipo de retorno de ya seaIEnumerable<T>
oIEnumerator<T>
.
De todos modos, voy a dejar que realice las correcciones de código a lo que he publicado mentalmente.
* Esto es puramente ilustrativo; No reclamo su exactitud real. Es solo para demostrar de una manera general cómo el compilador hace lo que hace, según la evidencia que he visto en mis propias investigaciones.
Además, el tipo generado por el compilador tendrá el nombre '
El compilador generará automáticamente una clase que implemente IEnumerable<T>
y IEnumerator<T>
(en la misma clase).
+1 para el enlace. – stacker
Agregue las partes relevantes del enlace a su respuesta –
La aplicación concreta de IEnumerable<string>
devuelto por el método es un tipo anónimo generado por el compilador
Console.WriteLine(GetIEnumerable().GetType());
Prints:
YourClass+<GetIEnumerable>d__0
Este es un azúcar sintáctico. mucho está sucediendo bajo el capó. La forma más rápida de verlo es usar el reflector. Básicamente, crea una clase que mantiene un estado y devuelve "a" cuando se llama a 'GetNext()' o algo así. –
@Timwi gracias por la edición :) – stacker