The Value property looks like this in the original source:
public short Value { get { if (m_size == 2) return (short) (m_s1 << 8 | m_s2); return (short) m_s2; } }
This looks pretty normal, m_s2 is always the least significant byte. Looking at ILGenerator:
internal void InternalEmit(OpCode opcode) { if (opcode.m_size == 1) { m_ILStream[m_length++] = opcode.m_s2; } else { m_ILStream[m_length++] = opcode.m_s1; m_ILStream[m_length++] = opcode.m_s2; } UpdateStackSize(opcode, opcode.StackChange()); }
What do you expect, byte 0xfe is first issued.
Thus, the program code carefully avoids end-user dependency. CIL is not dependent on endian-ness; variable-length data is never executed. True for text files, utf-8 encoding, instructions for x86 machine code. CIL. Therefore, if you convert variable-length data to a single value, for example, the getter property of a property, then this code inevitably does the conversion from non-infinite data to endian-ness data. This inevitably leads to the fact that half the world is upset because it thinks it was wrong. And 100% of all programmers who encounter this.
Probably the best way is to do as the framework does, and restore m_s1 and m_s2 as fast as you can, using your own version of the Opcode type. Simple approach:
foo.m_s1 = opc.Value >> 8; foo.m_s2 = opc.Value & 0xff; foo.m_size = opc.Size;
which has no dependence on the end.
Hans passant
source share