It does matter. You want your comparison to have the same result as SQL Server's comparison. SQL Server uses unsigned comparisons on binary types:
select case when 0x0FFFFFFFFFFFFFFF < 0xFFFFFFFFFFFFFFFF then 'unsigned' else 'signed' end
If you do the same thing with long
which is signed, 0xFFFFFFFFFFFFFFFF
represents -1
. That means your comparison will be incorrect; it won't match with the same comparison done in SQL Server.
What you definitely want is to use ulong
where 0xFFFFFFFFFFFFFFFF
is ulong.MaxValue
.
Endianness is also important
Additionally, as Mark pointed out, BitConverter.GetUInt64
is not converting properly. Mark is not completely right- BitConverter
is either big-endian or little-endian depending on the system it's running on. You can see this for yourself. Also, even if BitConverter was always little-endian, Array.Reverse
is less performant with a heap allocation and byte-by-byte copying. BitConverter
is just not semantically or practically the right tool for the job.
This is what you want:
static ulong BigEndianToUInt64(byte[] bigEndianBinary)
{
return ((ulong)bigEndianBinary[0] << 56) |
((ulong)bigEndianBinary[1] << 48) |
((ulong)bigEndianBinary[2] << 40) |
((ulong)bigEndianBinary[3] << 32) |
((ulong)bigEndianBinary[4] << 24) |
((ulong)bigEndianBinary[5] << 16) |
((ulong)bigEndianBinary[6] << 8) |
bigEndianBinary[7];
}
The cleanest solution
Update: If you use .NET Core 2.1 or later (or .NET Standard 2.1), you can use BinaryPrimitives.ReadUInt64BigEndian
which is a perfect fit.
On .NET Framework, here is the solution I use: Timestamp.cs. Basically once you cast to Timestamp
, you can't go wrong.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…