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