Zoptymalizowałem metodę rozszerzenia, aby porównać dwa strumienie dla równości (bajt po bajcie) - wiedząc, że jest to gorąca metoda, którą starałem się zoptymalizować w miarę możliwości (strumienie może osiągnąć wielomagabajtowe długości). I w istocie wpadł następującej metody:Jeśli komunikat Prawdziwy blok został wykonany, gdy warunek jest fałszywy
[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;
}
}
}
}
Problemem jest to, że blok convert1.UInt64[i] != convert2.UInt64[i]
if
(powrót false
) jest oceniany nawet wtedy, gdy wartości są równe. Sprawdziłem każdy indywidualnie, a następnie sprawdziłem wynik "nie jest równy". Jestem w czystej niedowierzaniem:
nie mam pomieszane ze wskaźnikiem instrukcji - w ten sposób kod wykonywany i kołek zegarek jest na żywo.
Jakieś pomysły, jak to może się stać?
czy działa, jeśli dodasz {} – rerun
wygląda jak porównanie odniesienia (różne obiekty, zawsze fałszywe) ma miejsce zamiast porównywania wartości – Alex
Jestem zdezorientowany, obie właściwości struktury mają FieldOffset 0, skąd wiesz, że "Porównujesz jabłka i jabłka? – mtijn