C# SortedSet<T> and equality

你。 提交于 2019-12-30 05:59:12

问题


I am a bit puzzled about the behaviour of SortedSet, see following example:

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());
}

So SortedSet discards entries if Compare(x,y) returns 0. Can I prevent this, such that my SortedSet behaves like HashSet and discards entries only if Equals() returns true?


回答1:


You can do this if you provide an alternate comparison when the Values are equal and the Compare method would otherwise return 0. In most cases this would probably just defer the problem instead of solving it. As others have noted, the SortedSet discards duplicates and when you provide a custom comparer it uses that to determine duplicity.

    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:


Description

SortedSet: You have many elements you need to store, and you want to store them in a sorted order and also eliminate all duplicates from the data structure. The SortedSet type, which is part of the System.Collections.Generic namespace in the C# language and .NET Framework, provides this functionality.

According to MSDN Compare method returns

  • Less than zero if x is less than y.
  • Zero if x equals y.
  • Greater than zero if x is greater than y.

More Information

  • Dotnetperls - C# SortedSet Examples
  • MSDN: Compare Method

Update

If your Bla class implements IComparable and you want your list sorted you can do this.

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

If your Bla class NOT implements IComparable and you want your list sorted you can use Linq (System.Linq namespace) for that.

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



回答3:


You can't find the other Blah(2) because you're using a Set.

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

MultiSet, for instance, allows duplicate objects.



来源:https://stackoverflow.com/questions/8604149/c-sharp-sortedsett-and-equality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!