2012-05-02 9 views
32

Tengo una pregunta sobre orden en IEnumerable (o IEnumerable<T>, no importa).IEnumerable y orden

Como sabemos, la iteración a través de IEnumerable es pseudo-código se puede escribir de la siguiente manera:

while (enumerable.HasNext()) 
{ 
    object obj = enumerable.Current; 
    ... 
} 

Ahora, supongamos que uno necesita para operar en un ordenados colección. ¿Se puede usar IEnumerable en este caso o es mejor probar otros medios (por ejemplo, IList) con soporte de indexación?

En otras palabras: ¿el contrato de IEnumerable hace alguna garantía sobre el pedido en general?

UPD: Por lo tanto, IEnumerable no es el medio adecuado para una interfaz genérica que garantiza el pedido. La nueva pregunta es ¿qué interfaz o clase se debe usar para una colección inmutable con el pedido? ReadonlyCollection? IList? Ambos contienen el método Add() (incluso no está implementado en el anterior). ¿Alguna sugerencia?

P.S Mis propios pensamientos: IEnumerable no ofrece ninguna garantía sobre el pedido. La implementación correcta podría devolver los mismos elementos en orden diferente en diferentes enumeraciones (considere una consulta SQL)

P.P.S. Soy consciente de LINQ First(), pero si IEnumerable no dice una palabra sobre su orden, esta extensión es bastante inútil.

Respuesta

25

IEnumerable/IEnumerable<T> no garantiza el orden, pero las implementaciones que usan IEnumerable/IEnumerable<T> pueden o no garantizar el pedido.

Por ejemplo, si usted enumerar List<T>, el orden está garantizado, pero si enumerar HashSet<T> se proporciona ninguna garantía de tal, sin embargo, ambos se enumerarán utilizando la interfaz IEnumerable<T>.

+1

Otro ejemplo es 'Dictionary <,>'. Está claramente documentado que el orden en que se enumeran sus entradas no está definido. Así que el código como 'dict.Last(). Key' (donde' dict' es un 'Dictionary <,> 'y' Last() 'es el método de extensión LINQ) no tiene sentido. (He oído hablar de un desarrollador que está haciendo exactamente eso). –

+1

Añadiría que ya dije que es importante entender correctamente qué garantías hay sobre el pedido de una colección genérica. Por lo tanto, la garantía de pedido no se trata de un orden en particular (por ejemplo, como resultado de la clasificación), sino de garantizar que el orden de los elementos de la misma colección sea el mismo para las enumeraciones posteriores. La mayoría de las colecciones no garantizan explícitamente eso. IList solo representa un tipo de diccionario donde las claves son índices. –

+0

IOrderedEnumerable puede ser un signo para creer que la colección garantiza el pedido (aunque la interfaz aún no lo hace), pero es más de lo que necesitamos; por lo general, representa un pedido SORT particular, mientras que NECESITAMOS CUALQUIER orden (aleatorio) que sea justo garantizado entre enumeraciones. Para concluir, solo la implementación concreta realmente puede garantizar el orden (por ejemplo, Matriz, Lista ). –

12

Detalle de implementación. IEnumerable enumerará el elemento; cómo se implementa esto depende de la implementación. Las listas MOST, etc. se ejecutan a lo largo de su orden natural (índice 0 hacia arriba, etc.).

¿el contrato de IEnumerable nos garantiza algún orden en el caso general?

No, garantiza la enumeración solamente (cada elemento una vez, etc.). IEnumerable no tiene un orden garantizado porque también se puede usar en elementos no ordenados.

Sé acerca de LINQ First(), pero si IEnumerable no dice una palabra acerca de su orden, esta extensión es bastante inútil.

No, no lo es, porque puede tener un orden intrínseco. Le da SQL como ejemplo: el resultado es un IEnumerable, pero si he ordenado antes el pedido (Al usar OrderBy()), entonces el IEnumerable se ordena por definición de LINQ. AsEnumerable(). First() obtiene entonces el primer artículo por orden.

4

Usted mezcla dos puntos: enumerar y ordenar.

Cuando enumera más de IEnumerable, no debería preocuparse por el pedido. Usted trabaja con la interfaz y su implementación debe preocuparse por el orden.

Por ejemplo:

void Enumerate(IEnumerable sequence) 
{ 
    // loop 
} 

SortedList<T> sortedList = ... 
Enumerate (sortedList); 

Dentro del método que sigue siendo una lista con orden fijo, pero el método no sabe nada de particular, la implementación de interfaces y es peculiaridad.

6

Quizás esté buscando la interfaz IOrderedEnumerable? Es devuelto por métodos de extensiones como OrderBy() y permite una clasificación posterior con ThenBy().

+0

Lamentablemente, esto no funcionará si desea aceptar interfaces como IList que sí garantizan un pedido pero no heredan de IOrderedEnumerable. Ver http://stackoverflow.com/q/5429974/1157054 – Ajedi32

Cuestiones relacionadas