Firstly, let's rewrite this in a more readable form:
(ulong)(uint)(
(int) this.m_buffer[4] |
(int) this.m_buffer[5] << 8 |
(int) this.m_buffer[6] << 16 |
(int) this.m_buffer[7] << 24)
<< 32 |
(ulong)(uint)(
(int) this.m_buffer[0] |
(int) this.m_buffer[1] << 8 |
(int) this.m_buffer[2] << 16 |
(int) this.m_buffer[3] << 24)
Now it's clear what this is doing.
It is combining the low 32 and high 32 bits into two separate uint
values (by shifting the bytes after casting them to int
), then casting the two resulting int
values to ulong
, shifting the high 32 bits by 32 and finally ORing them together to get the result.
The reason it does this is because it is faster to shift 32 bit values than it is to shift 64 bit values. If the code cast all the bytes to ulong
and then shifted them, it would be slower.
Also note that the order in which it is combining the bytes is for "little endian" format.
The only apparently weird thing is the first cast (ulong)(uint)
, which could just be (ulong)
. If you remove all the unnecessary casts, it looks like this:
(ulong)(
buffer[4] |
buffer[5] << 8 |
buffer[6] << 16 |
buffer[7] << 24)
<< 32 |
(uint)(
buffer[0] |
buffer[1] << 8 |
buffer[2] << 16 |
buffer[3] << 24);
Now you might wonder why you can't just cast to ulong
instead of uint
.
The answer to this is as follows. Suppose the code was like this:
(ulong)(
buffer[4] |
buffer[5] << 8 |
buffer[6] << 16 |
buffer[7] << 24)
<< 32 |
(ulong)( // This seems more natural...
buffer[0] |
buffer[1] << 8 |
buffer[2] << 16 |
buffer[3] << 24);
The first part of the expression is shifted using ulong.operator<<()
as a result of the cast to (ulong)
. This returns a (ulong)
.
However the second part of the expression is NOT shifted, and when ORing it with the first expression it prompts a compiler warning:
warning CS0675: Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first
Eric Lippert has a blog about this warning which you should read.
Anyway, because it looks weird when casting to (ulong)
in the first part and (uint)
in the second part, I'm fairly sure they put in the full explicit casts to prevent confusion on the part of the reader.