简体   繁体   English

C#字节数组比较

[英]C# byte array comparison

I have two byte arrays in C# using .NET 3.0. 我使用.NET 3.0在C#中有两个字节数组。

What is the "most efficient" way to compare whether the two byte arrays contains the same content for each element? 比较两个字节数组是否包含每个元素的相同内容的“最有效”方法是什么?

For example, byte array {0x1, 0x2} is the same as {0x1, 0x2} . 例如,字节数组{0x1, 0x2}{0x1, 0x2} But byte array {0x1, 0x2} and byte array {0x2, 0x1} are not the same. 但字节数组{0x1, 0x2}和字节数组{0x2, 0x1}不相同。

Well, you could use: 好吧,你可以使用:

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

(I normally use braces for everything, but I thought I'd experiment with this layout style just for a change...) (我通常会使用大括号来表示所有内容,但我认为我只是为了改变而尝试这种布局样式......)

This has a few optimisations which SequenceEqual can't (or doesn't) perform - such as the up-front length check. 这有一些优化, SequenceEqual不能(或不执行) - 例如前期长度检查。 Direct array access will also be a bit more efficient than using the enumerator. 直接阵列访问也比使用枚举器更有效。

Admittedly it's unlikely to make a significant difference in most cases... 无可否认,在大多数情况下不太可能产生显着差异......

You could possibly make it faster in unmanaged code by making it compare 32 or 64 bits at a time instead of 8 - but I wouldn't like to code that on the fly. 您可以通过使其在一个时间,而不是8比32个或64位可能使其更快非托管代码-但我不喜欢代码的飞行。

You can use the SequenceEqual method: 您可以使用SequenceEqual方法:

bool areEqual = firstArray.SequenceEqual(secondArray);

As mentioned in the comments, SequenceEqual requires .NET 3.5 (or LINQBridge if you're using VS2008 and targeting an earlier version of the framework). 正如评论中所提到的, SequenceEqual需要.NET 3.5(如果您使用的是VS2008并且针对早期版本的框架,则需要LINQBridge )。

Jon mentioned comparing multiple bytes at once using unsafe code, so I had to give it a go: 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;
}

The safe code gets pretty optimised (the compiler knows that it doesn't have to check index boundaries for example), so I wouldn't expect the unsafe code to be very much faster. 安全代码得到了相当优化(例如,编译器知道它不必检查索引边界),所以我不希望不安全代码更快。 Any significant difference would come from the ability to compare several bytes at once. 任何显着差异都来自于一次比较几个字节的能力。

If you are not too concerned about performance, you can consider IStructuralEquatable . 如果您不太关心性能,可以考虑IStructuralEquatable

.NET Framework Supported in: 4.5, 4 .NET Framework受以下版本支持:4.5,4

Structural equality means that two objects are equal because they have equal values. 结构相等意味着两个对象是相等的,因为它们具有相等的值。 It differs from reference equality. 它与参考相等不同。

Example: 例:

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

REFERENCE 参考

  1. What problem does IStructuralEquatable and IStructuralComparable solve? IStructuralEquatable和IStructuralComparable解决了什么问题?
  2. Why aren't IStructuralEquatable and IStructuralComparable generic? 为什么IStructuralEquatable和IStructuralComparable不通用?
  3. IStructuralEquatable Interface IStructuralEquatable接口

If you want it to be really fast, you can use unsafe code (which isn't always possible): 如果你想要它真的很快,你可以使用不安全的代码(这并不总是可行):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM