Jon*_*son 10 c# logic conditional
我优化了一个扩展方法来比较两个流的相等性(逐字节) - 知道这是一个热门的方法,我试图尽可能地优化它(流可以达到数兆字节的长度).我基本上想出了以下方法:
[StructLayout(LayoutKind.Explicit)]
struct Converter
{
[FieldOffset(0)]
public Byte[] Byte;
[FieldOffset(0)]
public UInt64[] UInt64;
}
/// <summary>
/// Compares two streams for byte-by-byte equality.
/// </summary>
/// <param name="target">The target stream.</param>
/// <param name="compareTo">The stream to compare the target to.</param>
/// <returns>A value indicating whether the two streams are identical.</returns>
public static bool CompareBytes(this Stream target, Stream compareTo)
{
if (target == null && compareTo == null)
return true;
if (target == null || compareTo == null)
return false;
if (target.Length != compareTo.Length)
return false;
if (object.ReferenceEquals(target, compareTo))
return true;
if (!target.CanRead || !target.CanSeek)
throw new ArgumentOutOfRangeException("target");
if (!compareTo.CanRead || !compareTo.CanSeek)
throw new ArgumentOutOfRangeException("target");
lock (target)
{
lock (compareTo)
{
var origa = target.Position;
var origb = compareTo.Position;
try
{
target.Position = compareTo.Position = 0;
// Shrink the number of comparisons.
var arr1 = new byte[4096];
var convert1 = new Converter() { Byte = arr1 };
var arr2 = new byte[4096];
var convert2 = new Converter() { Byte = arr2 };
int len;
while ((len = target.Read(arr1, 0, 4096)) != 0)
{
if (compareTo.Read(arr2, 0, 4096) != len)
return false;
for (var i = 0; i < (len / 8) + 1; i++)
if (convert1.UInt64[i] != convert2.UInt64[i])
return false;
}
return true;
}
finally
{
target.Position = origa;
compareTo.Position = origb;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是即使值相等,也会评估convert1.UInt64[i] != convert2.UInt64[i] if块(返回false).我单独检查每个,然后检查'不等于'的结果.我完全不相信:

我没有搞乱指令指针 - 这是执行代码和监视引脚的实时方式.
任何想法如何发生这种情况?
Han*_*ant 11
for (var i = 0; i < (len / 8) + 1; i++)
Run Code Online (Sandbox Code Playgroud)
调试器通常很难用这个联合,它在我尝试时无法显示数组内容.但核心问题无疑是for()结束表达式中的+1.当len可被8整除时,将数组索引到其最后一个元素之外.运行时无法捕获此错误,重叠数组会导致Length属性具有伪值.接下来发生的是未定义的行为,您正在读取不属于该数组的字节.解决方法是使数组长7个字节.
这种代码并不完全是一种优化,在32位机器上读取和比较uint64是很昂贵的,特别是当阵列没有正确对齐时.大约50%的可能性.更好的捕鼠器是使用任何Windows机器上可用的C运行时memcmp()函数:
[DllImport("msvcrt.dll")]
private static extern int memcmp(byte[] arr1, byte[] arr2, int cnt);
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
int len;
while ((len = target.Read(arr1, 0, 4096)) != 0) {
if (compareTo.Read(arr2, 0, 4096) != len) return false;
if (memcmp(arr1, arr2, len) != 0) return false;
}
return true;
Run Code Online (Sandbox Code Playgroud)
比较它的perf与用于比较字节的plain for()循环.这里的最终节流是内存总线带宽.