Pregunta

Me preguntaba por qué el método GetEnumerator () se factoriza de IEnumerator y se coloca en IEnumerable. Me parece que tendría más sentido para mantener todos los métodos empadronador en IEnumerator.

Gracias,

Scott

¿Fue útil?

Solución

Pregúntese "imaginar si esto fuera cierto".

Si todos los métodos de enumeración estaban en una única interfaz, ¿cómo podrían dos personas que llaman enumerar la misma lista al mismo tiempo?

Hay dos interfaces, porque uno dice, "Usted me puede enumerar", mientras que el otro dice, "aquí está un objeto que realiza un seguimiento de una tarea enumeración dada."

La interfaz IEnumerable es una fábrica que crea muchos objetos como IEnumerator como desee. ¿Cómo y cuándo estos encuestadores se acostumbran es hasta el consumidor.

Otros consejos

IEnumerable implica que el objeto es una colección o fuente de datos que pueden ser repiten a lo largo de una forma lineal. IEnumerator es la interfaz de la aplicación real que realiza la iteración.

Debido a que "IEnumerable" dice "ven, Enumerar mí" (y luego decir- cómo, dame el enumerador), sin embargo "IEnumerator" dice "Puedo enumerar su colección!" y ya lo tienes, no es necesario para conseguir más.

Se puso muy buenas respuestas aquí. Sólo un poco de énfasis. Un enumerador mantiene estado, se realiza un seguimiento del objeto actual de la colección que se enumeran. Disponible a través de IEnumerator.Current. Y sabe cómo cambiar ese estado, IEnumerator.MoveNext (). Mantener estado requiere un objeto separado que almacena el estado. Ese estado no se puede almacenar en el interior del objeto de colección con facilidad debido a que sólo hay un objeto de colección, pero no puede haber más de un empadronador.

Me usó la frase "fácilmente", ya que es realmente posible para una colección para realizar un seguimiento de sus encuestadores. Después de todo, era una llamada al método de la clase de colección GetEnumerator () que devuelve el iterador. Hay una clase de colección en el marco .NET que hace esto, Microsoft.VisualBasic.Collection. Es necesario implementar un contrato de VB6 para su clase Recogida y que especifica los contratos que el cambio de una colección mientras se está empadronado es legal. Lo que significa que cuando se modifica la colección, es necesario que alguna razonable con todos los objetos del iterador que se crearon.

Se les ocurrió un truco bastante bueno, WeakReference podría haber sido inspirado por esto. Echar un vistazo-ver en el código que se muestra por el reflector. Inspirar cosas. Cavar un poco más y encontrar "versión" en las clases de colección. truco impresionante.

Debido a que a menudo lo hace la enumeración es sólo tangencialmente (en su caso) en relación con lo que se enumeran. Si IEnumerable y IEnumerator eran la misma interfaz, no podían ser compartidos, o que había necesidad de tener algún argumento sin tipo en GetEnumerator que le ha permitido pasar en el objeto de estar numerado. La división de ellas permite que la infraestructura de la enumeración sea potencialmente compartida a través de diferentes tipos.

Después de leer el post de Bart De Smet en minlinq ya no estoy convienced que la división de las dos interfaces es estrictamente necesario.

Por ejemplo - en el siguiente enlace, IEnumerable / IEnumerator se collaped a un único método de interfaz

Func<Func<Option<T>>>

y algunas implementaciones básicas

public static class FEnumerable
{
    public static Func<Func<Option<T>>> Empty<T>()
    {
        return () => () => new Option<T>.None();
    }

    public static Func<Func<Option<T>>> Return<T>(T value)
    {
        return () =>
        {
            int i = 0;
            return () =>
                i++ == 0
                ? (Option<T>)new Option<T>.Some(value)
                : (Option<T>)new Option<T>.None();
        };
    }

    ...

}

public static Func<Func<Option<T>>> Where<T>(this Func<Func<Option<T>>> source, Func<T, bool> filter)
{
    return source.Bind(t => filter(t) ? FEnumerable.Return(t) : FEnumerable.Empty<T>());
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top