0

私のコードには、コレクションの並べ替えメソッドが実装されていますが、今日、奇妙なことに気付きました。列挙型に新しい列挙値を追加しようとすると、並べ替えメソッドがこのエラーでクラッシュしました。

IComparer.Compare() メソッドが一貫性​​のない結果を返すため、並べ替えできません。値がそれ自体と比較されないか、ある値を別の値と繰り返し比較すると異なる結果が得られます。x: ''、x のタイプ: '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
4

3 に答える 3

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

よりシンプルでより重要なことに、実際に機能するはずです:)

于 2012-08-26T20:04:03.077 に答える
1

比較方法で従わなければならないいくつかのルールがあります。

  1. A == Bの場合、B == A(両方の時間でゼロを返します)。
  2. A<BおよびB<Cの場合、A<C。
  3. A <Bの場合、B> A
  4. A == A(それ自体と比較した場合はゼロを返します)。

==上記は、どちら<>真ではないことを意味します。2つのオブジェクトが、対応するオブジェクトに対して真でなくても、ソート順で同等であることが許容されますEquals。たとえば、数値を含むすべての文字列を番号順にソートするルールを設定できます。他のすべての文字列と最後を配置しますが、他の文字列がどのような順序であるかは気にしませんでした)。

これらのルールはどの言語にも適用されます(プログラミングルールではなく、ロジックルールです)。.NET固有のルールもあります。

5:A!= nullの場合、A>null。

最初の4つのルールすべてに違反しています。は参照型なので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)));
}

(これは、解析の失敗が不可能であり、考慮する必要がないことを前提としています)。

于 2012-08-26T21:47:18.220 に答える
1

エラーが明確に述べているように、比較機能が壊れています。

0値が等しい場合は返す必要があります。

于 2012-08-26T20:03:58.483 に答える