¿HashSet conserva el orden de inserción?

¿ HashSet colección HashSet introducida en .NET 3.5 conserva el orden de inserción cuando se itera usando foreach ?

La documentación indica que la colección no está ordenada, pero no dice nada sobre el orden de inserción. Una entrada de blog de BCL previa a la publicación indica que no está ordenada, pero este artículo indica que está diseñada para conservar el orden de inserción. Mis pruebas limitadas sugieren que ese orden se conserva, pero eso podría ser una coincidencia.

Esta página HashSet MSDN dice específicamente:

Un conjunto es una colección que no contiene elementos duplicados y cuyos elementos no están en ningún orden particular.

Creo que el artículo que afirma que conserva el orden es simplemente incorrecto. Para las pruebas simples, el orden de inserción puede conservarse debido a la estructura interna, pero no está garantizado y no siempre funcionará de esa manera. Trataré de encontrar un contraejemplo.

EDITAR: Aquí está el contraejemplo:

 using System; using System.Collections.Generic; class Test { static void Main() { var set = new HashSet(); set.Add(1); set.Add(2); set.Add(3); set.Remove(2); set.Add(4); foreach (int x in set) { Console.WriteLine(x); } } } 

Esto imprime 1, 4, 3 a pesar de 3 haber sido insertado antes de 4.

Es posible que si nunca elimina ningún elemento, conservará el orden de inserción. No estoy seguro, pero no estaría del todo sorprendido. Sin embargo, creo que sería una muy mala idea confiar en eso:

  • No está documentado que funcione de esa manera, y la documentación declara explícitamente que no está ordenada.
  • No he analizado las estructuras internas o el código fuente (que obviamente no tengo). Tendría que estudiarlos detenidamente antes de hacer una afirmación de este tipo de manera firme.
  • La implementación podría cambiar muy fácilmente entre las versiones del marco. Confiar en esto sería como confiar en la string.GetHashCode implementación de string.GetHashCode no cambia, lo que algunas personas hicieron en .NET 1.1 días, y luego se quemaron cuando la implementación cambió en .NET 2.0 …

La documentación dice:

Una colección HashSet <(Of <(T>)>) no está ordenada y no puede contener elementos duplicados. Si la duplicación de orden o elemento es más importante que el rendimiento para su aplicación, considere usar la clase List <(Of <(T>)>) junto con el método Sort.

Por lo tanto, no importa si realmente conserva el orden de los elementos en la implementación actual, porque no está documentado como hacerlo, e incluso si parece que ahora esto puede cambiar en cualquier momento en el futuro (incluso en una revisión de el marco).

Debería progtwigr contra contratos documentados , no detalles de implementación .

No, un conjunto de hash no conservará el orden de inserción, al menos no de forma predecible. Podría usar un LinkedHashSet (Java) o un equivalente. Un LinkedHashSet conservará el orden.

Si quieres un pedido, ni siquiera deberías estar usando un conjunto … no está hecho para elementos ordenados, excepto en casos excepcionales.

EDITAR: suena como si estuviera predicando: – Lo siento.

Existe específicamente una SortedSet en .NET4 .

Esto le daría una clasificación, pero es poco probable que sea una ordenación de orden de inserción. Como puede usar un IComparer personalizado, en IComparer podría hacer que esto haga cualquier cosa.

Al leer el código fuente de HashSet.AddIfNotPresent , puede ver que el orden de inserción se conserva suponiendo que no ha habido ninguna eliminación .

Así, el new HashSet { "Tom", "Dick", "Harry" } conserva el orden, pero si luego quita a Dick y agrega a Rick, el pedido será [“Tom”, “Rick”, “Harry”].