【问题标题】:Sort stop working after enum values added添加枚举值后排序停止工作
【发布时间】:2012-08-26 19:58:24
【问题描述】:

我的代码中有一个用于集合的排序方法,今天我发现了一些奇怪的东西。当我尝试向枚举添加新的枚举值时,排序方法因此错误而崩溃。

无法排序,因为 IComparer.Compare() 方法返回不一致的结果。一个值与自身比较不相等,或者一个值与另一个值重复比较会产生不同的结果。 x: '', x's type: 'Texture2D', IComparer: 'System.Array+FunctorComparer`1[Microsoft.Xna.Framework.Graphics.Texture2D]'。

这看起来真的很奇怪,现在排序依赖于早期结果,它应该做的只是在枚举索引之后排序,而不是字母顺序。

这里是代码。

    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

【问题讨论】:

  • 如果 A 和 B 相等,您的代码对 A>BB>A 都返回 -1

标签: c# sorting enums


【解决方案1】:

您的比较 从不 返回 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);
}

更简单,更重要的是,它实际上应该工作 :)

【讨论】:

  • 除非空 Texture2D 可能在已排序的集合中,在这种情况下您将抛出 NullReferenceException
【解决方案2】:

正如错误明确指出的那样,您的比较器已损坏。

如果值相等,则需要返回0

【讨论】:

    【解决方案3】:

    任何比较方法都必须遵循一些规则:

    1. 如果 A == B,则 B == A(两次都返回零)。
    2. 如果 A
    3. 如果 A A
    4. A == A(如果与自身比较,则返回零)。

    (注意,上面的== 意味着<> 都不为真。允许两个对象在排序顺序上等价,而对应的Equals 不为真。我们可以例如,有一个规则将所有包含数字的字符串按数字顺序排序,将所有其他字符串放在末尾,但不关心其他字符串的顺序)。

    这些规则适用于任何语言(它们不是编程规则,它们是逻辑规则),还有一个特定于 .NET 的规则:

    5:如果 A != null,则 A > null。

    你违反了前四个规则。由于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)));
    }
    

    (这假设解析失败是不可能的并且不必考虑)。

    【讨论】:

      猜你喜欢
      • 2016-04-25
      • 2014-01-06
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多