小编典典

比较 .NET 中的两个字节数组

all

我怎样才能快速做到这一点?

当然我可以这样做:

static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
    if (a1.Length != a2.Length)
        return false;

    for (int i=0; i<a1.Length; i++)
        if (a1[i]!=a2[i])
            return false;

    return true;
}

但我正在寻找BCL函数或一些高度优化的经过验证的方法来执行此操作。

java.util.Arrays.equals((sbyte[])(Array)a1, (sbyte[])(Array)a2);

工作得很好,但它看起来不适用于 x64。


阅读 110

收藏
2022-03-06

共1个答案

小编典典

用户 gil 建议了产生此解决方案的不安全代码:

// Copyright (c) 2008-2013 Hafthor Stefansson
// Distributed under the MIT/X11 software license
// Ref: http://www.opensource.org/licenses/mit-license.php.
static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) {
  if(a1==a2) return true;
  if(a1==null || a2==null || a1.Length!=a2.Length)
    return false;
  fixed (byte* p1=a1, p2=a2) {
    byte* x1=p1, x2=p2;
    int l = a1.Length;
    for (int i=0; i < l/8; i++, x1+=8, x2+=8)
      if (*((long*)x1) != *((long*)x2)) return false;
    if ((l & 4)!=0) { if (*((int*)x1)!=*((int*)x2)) return false; x1+=4; x2+=4; }
    if ((l & 2)!=0) { if (*((short*)x1)!=*((short*)x2)) return false; x1+=2; x2+=2; }
    if ((l & 1)!=0) if (*((byte*)x1) != *((byte*)x2)) return false;
    return true;
  }
}

它对尽可能多的数组进行基于 64 位的比较。这种依赖于数组开始 qword 对齐的事实。如果不是 qword 对齐,它会起作用,只是不像它那样快。

它比简单for循环执行大约七个定时器。使用 J# 库执行与原始for循环等效的操作。使用 .SequenceEqual
会慢七倍左右;我认为只是因为它使用的是 IEnumerator.MoveNext。我想基于 LINQ 的解决方案至少会那么慢或更糟。

2022-03-06