¿Cómo funcionan los conjuntos ordenados para c # con objetos personalizados? [duplicar]

Dec 14 2020

Estoy tratando de jugar con conjuntos ordenados en c # para objetos personalizados y, por alguna razón, parece que los conjuntos ordenados podrían no estar usando las referencias de los objetos para almacenar los datos.

En el siguiente fragmento de código, utilizo un IComparer personalizado para confiar en la propiedad Counts de la clase personalizada. Pero por alguna razón, esto parece afectar la funcionalidad de agregar. y el contador. La línea Add (two) no hace ninguna adición al conjunto aunque es una referencia diferente y tiene un valor diferente para dos propiedades.

¿Me estoy perdiendo de algo? ¿Tengo algo mal sobre cómo se supone que funcionan los SortedSets en C #?

Fragmento de código

    public class SortedStructureTesting
    {
        public void TestingSortedSets()
        {
            SortedSet<CounterSetup> counter = new SortedSet<CounterSetup>(new CompareCounts());

            CounterSetup one = new CounterSetup(1);
            CounterSetup two = new CounterSetup(2);
            CounterSetup three = new CounterSetup(3, 2);

            counter.Add(one);
            counter.Add(two); // Does not work. This value does not get added to the set.
            counter.Add(three);

            var max = counter.Max;
            counter.Remove(max);
            var sec = counter.Max;
            counter.Remove(sec);
        }

        public class CounterSetup
        {
            public static Random random = new Random();
            public CounterSetup(int no, int cnt = 1)
            {
                Number = no;
                Count = cnt;
                Blah = new string(Guid.NewGuid().ToString());
            }

            public int Number { get; private set; }

            public int Count { get; set; }

            public string Blah { get; private set; }
        }

        public class CompareCounts : IComparer<CounterSetup>
        {
            public int Compare(CounterSetup one, CounterSetup two)
            {
                return one.Count.CompareTo(two.Count);
            }
        }
    }

¡Gracias por echar un vistazo y ayudar!

Respuestas

1 DmitryBychenko Dec 14 2020 at 13:18

Bien solo [Sorted]Setpuede contener elementos distintos ; es decir Set, no puede haber dos elementos iguales más. Usted compara los elementos (trátelos como iguales) con respecto a Count: si dos elementos tienen lo mismo Count, se consideran iguales. En tu código

  CounterSetup one = new CounterSetup(1);         // one.Count == 1
  CounterSetup two = new CounterSetup(2);         // two.Count == 1
  CounterSetup three = new CounterSetup(3, 2);    // three.Count == 2

tienes one.Count == two.Count == 1por eso oney twoson iguales para el counterconjunto ordenado. Cuando agrega elementos, el segundo (que es two) se ignora:

  counter.Add(one);
  counter.Add(two); // Ignored: there's already an item (one) with the same Count
  counter.Add(three);

Si desea criterios separados (uno para Equalsy el otro es para el pedido) puede probar el buen viejo HashSetque puede representar como pedido con la ayuda de Linq :

  using System.Linq;

  ...

  // Items in counter are unique (based on MyEqualityComparer)
  HashSet<CounterSetup> counter = new HashSet<CounterSetup>(
    new MyEqualityComparer()
  );

  // Now we order counter items by different criterium (here we sort by `Count`)
  var ordered = counter
    .OrderBy(item => item.Count);