4
public class foo {
  int ID { get; set; }
  byte[] sort { get; set; }
}

public class barMaster {
    public void FooSource() {
        return List<foo> FromDataSource;
    }
    public void display() {
        List<foo> sortedFoo = FooSource().OrderBy(f => f.sort);
        UIElement = sortedFoo;
    }

OrderBy にしたい byte[] プロパティを含むオブジェクトのセットがありますが、 OrderBy(byte[]) はエラーをスローします。

System.ArgumentException: At least one object must implement IComparable.

OrderBy byte[] 値に対して何ができますか?

4

4 に答える 4

5

配列が可変長であることを示したように( SQL Server階層IDであるため)、カスタムIComparer<byte[]>実装を作成する必要があります。

ロジックは単純です。

  • n各アレイの最初のバイトをバイトごとに比較します。ここnで、は2つのアレイのうち小さい方のバイト数です。いずれかのバイト間で差異が検出された場合は、異なるバイトの比較結果を返します。
  • 最初のnバイトが等しい場合は、2つの配列の長さの比較を返します。

このように、次のようなデータセットが与えられます。

00 01 02
00 01
01

並べ替えると、次のような結果が得られます。

00 01
00 01 02
01

そうは言っても、これはあなたのIComparer<byte[]>実装がどのように見えるかです:

// I could be wrong in that this is called natural order.
class NaturalOrderByteArrayComparer : IComparer<byte[]>
{
    public int Compare(byte[] x, byte[] y)
    {
        // Shortcuts: If both are null, they are the same.
        if (x == null && y == null) return 0;

        // If one is null and the other isn't, then the
        // one that is null is "lesser".
        if (x == null && y != null) return -1;
        if (x != null && y == null) return 1;

        // Both arrays are non-null.  Find the shorter
        // of the two lengths.
        int bytesToCompare = Math.Min(x.Length, y.Length);

        // Compare the bytes.
        for (int index = 0; index < bytesToCompare; ++index)
        {
            // The x and y bytes.
            byte xByte = x[index];
            byte yByte = y[index];

            // Compare result.
            int compareResult = Comparer<byte>.Default.Compare(xByte, yByte);

            // If not the same, then return the result of the
            // comparison of the bytes, as they were the same
            // up until now.
            if (compareResult != 0) return compareResult;

            // They are the same, continue.
        }

        // The first n bytes are the same.  Compare lengths.
        // If the lengths are the same, the arrays
        // are the same.
        if (x.Length == y.Length) return 0;

        // Compare lengths.
        return x.Length < y.Length ? -1 : 1;
    }
}

余談ですが、バイト配列が同じ長さであることが保証されている場合は、別の方法として、次のように、order by句を動的に作成し、最初の要素、次に2番目の要素などで並べ替えることができます。

static IEnumerable<foo> OrderBySortField(this IEnumerable<foo> items, 
    int sortLength)
{
    // Validate parameters.
    if (items == null) throw new ArgumentNullException("items");
    if (sortLength < 0) throw 
        new ArgumentOutOfRangeException("sortLength", sortLength,
            "The sortLength parameter must be a non-negative value.");

    // Shortcut, if sortLength is zero, return the sequence, as-is.
    if (sortLength == 0) return items;

    // The ordered enumerable.
    IOrderedEnumerable<foo> ordered = items.OrderBy(i => i.sort[0]);

    // Cycle from the second index on.
    for (int index = 1; index < sortLength; index++)
    {
        // Copy the index.
        int indexCopy = index;

        // Sort by the next item in the array.
        ordered = ordered.ThenBy(i => i.sort[indexCopy]);
    }

    // Return the ordered enumerable.
    return ordered;
}

そして、あなたはそれをそのように単に呼ぶことができます:

// You have to supply the length of the array you're sorting on.
List<foo> sortedFoo = FooSource().
    OrderBySortField(sortLength).ToList();
于 2012-05-18T19:56:40.627 に答える
5

byte[]配列は を実装していないため、 で直接注文することはできませんIComparable。最初のバイト (つまりOrderBy(f => f.sort[0])、または他の適切なもの) で並べ替えるか、独自に記述してOrderByIComparer<byte[]>の適切なオーバーロードで使用する必要があります。

于 2012-05-18T19:36:15.517 に答える
0

残念ながら、私が知る限り、バイト配列でソートすることはできません。

できることは、foo クラスに IComparable を実装させることです。次に、オーバーライドされた compareTo メソッドで、呼び出しで好きなようにバイト配列の比較を記述します。次に、Order By を単純な並べ替えに置き換えることができます。

FooSource().Sort();   
于 2012-05-18T19:49:44.780 に答える