С# SortedSet <T> и равенство

Я немного озадачен поведением SortedSet, см. следующий пример:

public class Blah
{
    public double Value { get; private set; }

    public Blah(double value)
    {
        Value = value;
    }
}

public class BlahComparer : Comparer<Blah>
{
    public override int Compare(Blah x, Blah y)
    {
        return Comparer<double>.Default.Compare(x.Value, y.Value);
    }
}

public static void main()
{
    var blahs = new List<Blah> {new Blah(1), new Blah(2), 
                                new Blah(3), new Blah(2)}

    //contains all 4 entries
    var set = new HashSet<Blah>(blahs); 

    //contains only Blah(1), Blah(2), Blah(3)
    var sortedset = new SortedSet<Blah>(blahs, new BlahComparer());
}

Так SortedSet отбрасывает записи, если Compare (x, y) возвращает 0. Могу ли я предотвратить это, так что мой SortedSet ведет себя как HashSet и отбрасывает записи только в том случае, если Equals() возвращает true?

Ответ 1

Вы можете сделать это, если вы предоставите альтернативное сравнение, когда значения равны, и метод сравнения в противном случае вернет 0. В большинстве случаев это, вероятно, просто отложит проблему, а не решит ее. Как отмечали другие, SortedSet отбрасывает дубликаты, и когда вы предоставляете пользовательский сопоставитель, он использует это для определения двуличия.

    static void Main(string[] args)
    {
        var blahs = new List<Blah>
                        {
                            new Blah(1, 0), new Blah(2, 1),
                            new Blah(3, 2), new Blah(2, 3)
                        };

        blahs.Add(blahs[0]);

        //contains all 4 entries
        var set = new HashSet<Blah>(blahs);

        //contains all 4 entries
        var sortedset = new SortedSet<Blah>(blahs, new BlahComparer());

    }
}

public class Blah
{
    public double Value { get; private set; }

    public Blah(double value, int index)
    {
        Value = value;
        Index = index;
    }

    public int Index { get; private set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}

public class BlahComparer : Comparer<Blah>
{
    public override int Compare(Blah x, Blah y)
    {
        // needs null checks
        var referenceEquals = ReferenceEquals(x, y);
        if (referenceEquals)
        {
            return 0;
        }
        var compare = Comparer<double>.Default.Compare(x.Value, y.Value);
        if (compare == 0)
        {
            compare = Comparer<int>.Default.Compare(x.Index, y.Index);
        }
        return compare;
    }
}

Ответ 2

Описание

SortedSet: У вас есть много элементов, которые нужно сохранить, и вы хотите сохранить их в отсортированном порядке, а также устранить все дубликаты из структуры данных. Тип SortedSet, который является частью пространства имен System.Collections.Generic на языке С# и .NET Framework, обеспечивает эту функциональность.

В соответствии с методом MSDN Compare возвращает

  • Меньше нуля, если x меньше y.
  • Нуль, если x равно y.
  • Больше нуля, если x больше y.

Дополнительная информация

Update

Если ваш класс Bla реализует IComparable, и вы хотите, чтобы ваш список отсортирован, вы можете сделать это.

var blahs = new List<Blah> {new Blah(1), new Blah(2), 
                            new Blah(3), new Blah(2)};
blahs.Sort();

Если ваш Bla класс НЕ реализует IComparable, и вы хотите, чтобы ваш список отсортирован, вы можете использовать Linq (пространство имен System.Linq) для этого.

blahs = blahs.OrderBy(x => x.MyProperty).ToList();

Ответ 3

Вы не можете найти другой Blah(2), потому что используете Set.

Set - A collection of well defined and **distinct** objects

MultiSet, например, позволяет дублировать объекты.