我想知道如何使用SortedSet,可以按对象的一个属性进行排序,另一方面可以将Uniity设置为另一个属性。
这是我拥有的:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var bonusSortedSet = new SortedSet<Bonus>(new ComparerByNumber());
var bonus0 = new Bonus()
{
ID = "6479cc32-960d-4aa0-a62d-8c81e65085e8",
Number = 15
};
var bonus1 = new Bonus()
{
ID = "8e8a9c1b-1889-4c4c-b039-b1dbe005719b",
Number = 10
};
var bonus2 = new Bonus()
{
ID = "3453f78d-ce28-4ab1-a7a1-395063374f87",
Number = 11
};
var bonus3 = new Bonus()
{
ID = "8e8a9c1b-1889-4c4c-b039-b1dbe005719b",
Number = 12
};
bonusSortedSet.Add(bonus0);
bonusSortedSet.Add(bonus1);
bonusSortedSet.Add(bonus2);
bonusSortedSet.Add(bonus3);
foreach (var bonus in bonusSortedSet)
{
Console.WriteLine($"{bonus.ID} : {bonus.Number}");
}
}
}
public class Bonus : IEqualityComparer<Bonus>
{
public string ID { get; set; }
public int Number { get; set; }
public bool Equals(Bonus x, Bonus y)
{
return x.GetHashCode() == y.GetHashCode();
}
public int GetHashCode(Bonus obj)
{
return obj != null ? obj.ID.GetHashCode() : string.Empty.GetHashCode();
}
}
public class ComparerByNumber : IComparer<Bonus>
{
public int Compare(Bonus x, Bonus y)
{
return Math.Sign(x.Number - y.Number);
}
}
}
结果是:
我会期望的:
答案 0 :(得分:1)
您尚未实现任何代码来使Bonus
对象的ID
属性唯一,而仅使其Number
属性唯一。即使您这样做,例如:
public int Compare(Bonus x, Bonus y)
{
if (x.ID == y.ID) return 0;
return Math.Sign(x.Number - y.Number);
}
这可以在某些情况下起作用,但是完全由SortedSet<T>
的内部实现驱动,并且不太可能在99%的时间内起作用。
您不能让集合按一个属性排序,而唯一性则由另一个属性决定。如果要跟踪两个独立属性的顺序和唯一性,则需要两个集合对象。
答案 1 :(得分:0)
您的课程实现了IEqualityComparer<Bonus>
,这是错误的。您不想让奖金成为比较者,而是希望奖金可以平等。
此外,不要通过检查哈希码是否相同来实现Equals
。会发生哈希冲突(但使用GetHashCode
的情况很少见)。
尝试像这样编写Bonus
类型:
public sealed class Bonus
{
public string ID { get; set; }
public int Number { get; set; }
public override bool Equals(object obj)
{
if (obj is Bonus other)
{
return ID == other.ID;
}
return false;
}
public override int GetHashCode()
{
return ID?.GetHashCode() ?? 0;
}
}
然后使用隐式(默认)相等比较器创建一个HashSet<>
:
var bonusSet = new HashSet<Bonus>();
将确保集合成员在ID
中是唯一的。然后,您可以在枚举成员时使用Linq对成员进行排序:
foreach (var bonus in bonusSet.OrderBy(x => x.Number))
{
Console.WriteLine($"{bonus.ID} : {bonus.Number}");
}