18

.NET 3.0 を使用して、C# に 2 つのバイト配列があります。

2 つのバイト配列に各要素の同じ内容が含まれているかどうかを比較する「最も効率的な」方法は何ですか?

たとえば、バイト配列{0x1, 0x2}は と同じ{0x1, 0x2}です。しかし、バイト配列{0x1, 0x2}とバイト配列{0x2, 0x1}は同じではありません。

4

6 に答える 6

45

さて、あなたは使うことができます:

public static bool ByteArraysEqual(byte[] b1, byte[] b2)
{
    if (b1 == b2) return true;
    if (b1 == null || b2 == null) return false;
    if (b1.Length != b2.Length) return false;
    for (int i=0; i < b1.Length; i++)
    {
        if (b1[i] != b2[i]) return false;
    }
    return true;
}

(私は通常、すべてにブレースを使用しますが、変更のためだけにこのレイアウト スタイルを試してみようと思いました...)

これには、事前SequenceEqualの長さチェックなど、実行できない (または実行しない) いくつかの最適化があります。配列への直接アクセスは、列挙子を使用するよりも少し効率的です。

確かに、ほとんどの場合、大きな違いが生じる可能性は低いです...

一度に 8 ビットではなく 32 ビットまたは 64 ビットを比較するようにすることで、アンマネージ コードで高速化できる可能性がありますが、その場でコーディングしたくありません。

于 2009-09-07T14:04:49.750 に答える
27

SequenceEqual次の方法を使用できます。

bool areEqual = firstArray.SequenceEqual(secondArray);

コメントで述べたように、SequenceEqual.NET 3.5 (またはVS2008を使用していて、以前のバージョンのフレームワークをターゲットにしている場合はLINQBridge ) が必要です。

于 2009-09-07T14:04:27.130 に答える
5

Jon は、安全でないコードを使用して一度に複数のバイトを比較すると述べていたので、試してみる必要がありました。

public unsafe bool ByteArraysEqual(byte[] b1, byte[] b2) {
   if (b1 == b2) return true;
   if (b1 == null || b2 == null) return false;
   if (b1.Length != b2.Length) return false;
   int len = b1.Length;
   fixed (byte* p1 = b1, p2 = b2) {
      int* i1 = (int*)p1;
      int* i2 = (int*)p2;
      while (len >= 4) {
         if (*i1 != *i2) return false;
         i1++;
         i2++;
         len -= 4;
      }
      byte* c1 = (byte*)i1;
      byte* c2 = (byte*)i2;
      while (len > 0) {
         if (*c1 != *c2) return false;
         c1++;
         c2++;
         len--;
      }
   }
   return true;
}

安全なコードはかなり最適化されます (たとえば、コンパイラはインデックスの境界をチェックする必要がないことを認識しています)。大きな違いは、一度に複数のバイトを比較できることから生じます。

于 2009-09-07T14:38:49.883 に答える
3

パフォーマンスについてあまり気にしない場合は、を検討できますIStructuralEquatable

.NET Frameworkサポート対象:4.5、4

構造的同等性とは、2つのオブジェクトが等しい値を持っているため、それらが等しいことを意味します。参照の等式とは異なります。

例:

static bool ByteArrayCompare(byte[] a1, byte[] a2) 
{
  IStructuralEquatable eqa1 = a1;
  return eqa1.Equals(a2, StructuralComparisons.StructuralEqualityComparer);
}

参照

  1. IStructuralEquatableとIStructuralComparableはどのような問題を解決しますか?
  2. IStructuralEquatableとIStructuralComparableがジェネリックではないのはなぜですか?
  3. IStructuralEquatableインターフェイス
于 2013-03-01T07:11:17.657 に答える
2

本当に高速にしたい場合は、安全でないコードを使用できます (常に可能であるとは限りません)。

    public static bool ArraysEqual(byte[] b1, byte[] b2)
    {
        unsafe
        {
            if (b1.Length != b2.Length)
                return false;

            int n = b1.Length;

            fixed (byte *p1 = b1, p2 = b2)
            {
                byte *ptr1 = p1;
                byte *ptr2 = p2;

                while (n-- > 0)
                {
                    if (*ptr1++ != *ptr2++)
                        return false;
                }
            }

            return true;
        }
    }
于 2009-09-07T14:20:05.780 に答える