¿Hay algún tipo de colección ordenada en .NET?

Estoy buscando un contenedor que mantenga todos sus artículos en orden. Miré SortedList, pero eso requiere una clave por separado, y no permite duplicar claves. También podría usar un contenedor sin clasificar y ordenarlo explícitamente después de cada inserción.

Uso:

  • Inserción ocasional
  • Recorrido frecuente con el fin
  • Lo ideal es no trabajar con claves separadas del objeto real, utilizando una función de comparación para ordenar.
  • Se desea una clasificación estable para objetos equivalentes, pero no es obligatorio.
  • El acceso aleatorio no es obligatorio.

Me doy cuenta de que puedo construirme una estructura de árbol equilibrada, me preguntaba si el marco ya contiene semejante bestia.

    Es posible que desee echar un vistazo a las colecciones de energía de Wintellect . Está disponible en CodePlex y contiene bastantes colecciones que son muy útiles. La colección OrderedBag en el proyecto es exactamente lo que estás buscando. Utiliza esencialmente un árbol rojo-negro para proporcionar un tipo bastante eficiente.

    Para hacer el comentario de EBarr como respuesta, SortedSet desde .NET 4.0. Por supuesto, es un conjunto, lo que significa que no puedes tener duplicados.

    Extendería tu propia clase de lista que, como dijiste, simplemente ordena después de cada inserción. Dado que las inserciones son poco frecuentes, el rendimiento alcanzado sería mínimo, y la clasificación de una lista casi ordenada es rápida, en cualquier caso. Extienda la Lista genérica y anule el método Agregar para ordenar inmediatamente. Si el rendimiento se convierte en un problema, puede insertarlo para ahorrar tiempo. Además, puede poner en cola sus inserciones para hacer una sola inserción transversal para todos los valores que desea insertar.

    Si solo quiere seguir con las colecciones estándar, entonces la función Sort(IComparer<>) de la clase List<> es una que a menudo se ignora. Todo lo que necesita hacer es crear un Comparer<> adecuado para sus objetos. Por ejemplo:

     public class PositionDateComparer : IComparer { public int Compare(VehiclePosition x, VehiclePosition y) { if (x.DateTime == DateTime.MinValue) { if (y.DateTime == DateTime.MinValue) { // If x is null and y is null, they're // equal. return 0; } // If x is null and y is not null, y // is greater. return -1; } // If x is not null... // if (y.DateTime == DateTime.MinValue) // ...and y is null, x is greater. { return 1; } // ...and y is not null, compare the dates // if (x.DateTime == y.DateTime) { // x and y are equal return 0; } if (x.DateTime > y.DateTime) { // x is greater return 1; } // y is greater return -1; } } 

    A continuación, ejecute un vehiclePositionsList.Sort(new PositionDateComparer()) siempre que desee ordenar la lista antes de acceder a ella. Me doy cuenta de que esto puede no ser tan simple como un contenedor que se ordena automáticamente cada vez que agrega un nuevo objeto, pero para muchos (como yo!) Esto podría ser suficiente para hacer el trabajo correctamente sin requerir ninguna biblioteca adicional.

    Como mencioné anteriormente hoy aquí , la Biblioteca de Colección Genérica C5 tiene el contenedor adecuado para usted.

    Si la clave también es un atributo del objeto, puede probar System.Collections.ObjectModel.KeyedCollection . Es una clase abstracta, pero si tu llave es solo una propiedad del artículo, entonces es muy simple de obtener.

    Este es un viejo truco que utilicé en VB6 para ordenar las cosas alfabéticamente: use un objeto ListBox System.Windows.Forms y establezca su propiedad “Sorted” en true. En C #, puede insertar cualquier objeto en el cuadro de lista, y ordenará el objeto alfabéticamente por su valor ToString ():

    para un módulo de clase:


    usando System.Windows.Forms;

      static void Main(string[] args) { ListBox sortedList = new ListBox(); sortedList.Sorted = true; sortedList.Items.Add("foo"); sortedList.Items.Add("bar"); sortedList.Items.Add(true); sortedList.Items.Add(432); foreach (object o in sortedList.Items) { Console.WriteLine(o); } Console.ReadKey(); } 

    Esto mostrará:

    432
    bar
    foo
    Cierto