我的代码中有一个用于集合的imprmented排序方法,今天我发现了一些奇怪的东西。当我尝试向枚举添加新的枚举值时,sort方法因此错误而崩溃。
无法排序,因为IComparer.Compare()方法返回不一致的结果。要么值不等于自身,要么重复一个值与另一个值进行比较会产生不同的结果。 x:'',x的类型:'Texture2D',IComparer:'System.Array + FunctorComparer`1 [Microsoft.Xna.Framework.Graphics.Texture2D]'。
这看起来真的很奇怪,排序现在依赖于较早的结果,所有它应该做的是排序alumabatic命令的枚举索引。
这是代码。
availableTiles.Sort(CompareTilesToEnum);
private static int CompareTilesToEnum(Texture2D x, Texture2D y)
{
int xValue = (int) (Enum.Parse(typeof(TileTyp), x.Name, true));
int yValue = (int) (Enum.Parse(typeof(TileTyp), y.Name, true));
if (xValue > yValue)
{
return 1;
}
else
{
return -1;
}
}
public enum TileTyp
{
Nothing = -1,
Forest,
Grass,
GrassSandBottom,
GrassSandLeft,
GrassSandRight,
GrassSandTop,
Mounten,
Sand,
Snow,
Water,
GrassSandTopLeft,
GrassSandAll,
GrassSandBottomLeft,
GrassSandBottomRightLeft,
GrassSandBottomRightTop,
GrassSandBottomTopLeft,
GrassSandRightLeft,
GrassSandRightTop,
GrassSandRightTopLeft,
GrassSandBottomRight,
GrassSandBottomTop
}
我添加的值是
GrassSandBottomRight,
GrassSandBottomTop
答案 0 :(得分:4)
您的比较从不返回0 - 即使值相等。您有什么理由不要让int.CompareTo
比较这些值吗?
private static int CompareTilesToEnum(Texture2D x, Texture2D y)
{
int xValue = (int) (Enum.Parse(typeof(TileTyp), x.Name, true));
int yValue = (int) (Enum.Parse(typeof(TileTyp), y.Name, true));
return xValue.CompareTo(yValue);
}
更简单,更重要的是,它实际应该工作:)
答案 1 :(得分:1)
由于错误明确指出,您的比较器已损坏。
如果值相等,则需要返回0
。
答案 2 :(得分:1)
任何比较方法都必须遵循一些规则:
(注意,上面的==
表示默认<
和>
都是正确的。允许两个对象在排序顺序中是等价的而不是对应的Equals
。例如,我们可以有一个规则,按照数字顺序对包含数字的所有字符串进行排序,放置所有其他字符串和结尾,但不关心其他字符串的顺序。)
这些规则遵循任何语言(它们不是编程规则,它们是逻辑规则),也有特定于.NET的规则:
5:如果A!= null,则A&gt;空。
你违反了前四条规则。由于Texture2D
是一种引用类型,因此您可能会违反规则5(但会抛出不同的异常)。
你也很幸运.NET抓住了它。一个不同的排序算法很可能会因为更容易混淆的错误而崩溃或陷入无限循环,因为它发现项目6被报告为大于项目7并交换它们,然后很快发现项目6被报告为大于项目7并交换它们,然后很快找到......
private static int CompareTilesToEnum(Texture2D x, Texture2D y)
{
//Let's deal with nulls first
if(ReferenceEquals(x, y))//both null or both same item
return 0;
if(x == null)
return -1;
if(y == null)
return 1;
//Enum has a CompareTo that works on integral value, so why not just use that?
return Enum.Parse(typeof(TileTyp), x.Name, true)).CompareTo(Enum.Parse(typeof(TileTyp), y.Name, true)));
}
(这假设解析失败是不可能的,不必考虑)。