Ich habe eine Erweiterungsmethode optimiert, um zwei Streams auf Gleichheit (Byte für Byte) zu vergleichen - da dies eine wichtige Methode ist, habe ich versucht, sie so weit wie möglich zu optimieren (die Streams können eine Größe von mehreren Megabytes haben). Ich bin im Grunde auf den folgenden Ansatz gekommen:
[StructLayout(LayoutKind.Explicit)]
struct Converter
{
[FieldOffset(0)]
public Byte[] Byte;
[FieldOffset(0)]
public UInt64[] UInt64;
}
///
/// Vergleicht zwei Streams Byte für Byte auf Gleichheit.
///
/// Der Zielstream.
/// Der Stream, mit dem das Ziel verglichen werden soll.
/// Ein Wert, der angibt, ob die beiden Streams identisch sind.
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;
// Reduziere die Anzahl der Vergleiche.
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;
}
}
}
}
Das Problem ist, dass der convert1.UInt64[i] != convert2.UInt64[i]
if
-Block (Rückgabe von false
) auch dann bewertet wird, wenn die Werte gleich sind. Ich habe sie einzeln überprüft und dann das Ergebnis des 'Nichtgleich'-Zustands überprüft. Ich kann es kaum glauben:
Ich habe nicht mit dem Instruktionszeiger herumgespielt - so wurde der Code ausgeführt und der Watch-Pin ist aktiv.
Ideen dazu, wie dies passieren könnte?