我使用.NET 3.0在C#中有两个字节数组。
比较两个字节数组是否包含每个元素的相同内容的“最有效”方法是什么?
例如,字节数组{0x1, 0x2}
与{0x1, 0x2}
相同。但是字节数组{0x1, 0x2}
和字节数组{0x2, 0x1}
不一样。
答案 0 :(得分:37)
好吧,你可以使用:
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
不能(或不能)执行的优化 - 例如前期长度检查。直接阵列访问也比使用枚举器更有效。
不可否认,在大多数情况下不太可能产生显着差异......
你可以可能通过一次比较32或64位而不是8来使非托管代码更快 - 但我不想动态编码。
答案 1 :(得分:26)
您可以使用SequenceEqual
方法:
bool areEqual = firstArray.SequenceEqual(secondArray);
正如评论中所提到的,SequenceEqual
需要.NET 3.5(或LINQBridge如果您使用的是VS2008并且定位于早期版本的框架。)
答案 2 :(得分: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;
}
安全代码得到了相当优化(例如,编译器知道它不必检查索引边界),因此我不希望不安全的代码更快。任何重大差异都来自于一次比较几个字节的能力。
答案 3 :(得分:3)
如果您不太关心性能,可以考虑IStructuralEquatable
。
.NET Framework受以下版本支持:4.5,4
结构相等意味着两个对象相等,因为它们具有相等的值。它与参考相等不同。
示例:
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
IStructuralEquatable eqa1 = a1;
return eqa1.Equals(a2, StructuralComparisons.StructuralEqualityComparer);
}
<强>参考强>
答案 4 :(得分: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;
}
}