Search code examples
c#castingendianness

Convert byte array to collection of enums in C#


I have a byte array that recevies enums in little endianess byte order from a function GetData() and I want to convert the array into a collection of enums. How would I copy and cast the bytes in LE order to the enum values in C#? I have a C++ background and not too familiar with the language. This is a sample code snippet:

public enum BarID
{
  TAG0 = 0x0B01,
  TAG1 = 0x0B02,
}

public class TestClass
{
  List<BarID> ids;
  internal TestClass() 
  {
      ids = new List<BarID>();
      byte[] foo = GetData(); // returns  01 0b 00 00 02 0b 00 00
      // cast byte array so that ids contains the enums 'TAG0' and 'TAG1'      

  }
}

Solution

  • Though Marc's answer is both good and fast, that works only on .NET Core, or if you use additional nugets. If that could be a problem (or you target older Framework versions) you can use a solution like this:

    var bytes = new byte[] { 0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00 };
    
    return BitConverter.IsLittleEndian
        ? ConvertLittleEndian(bytes)
        : ConvertBigEndian(bytes);
    

    Where the conversion methods:

    private static unsafe BarID[] ConvertLittleEndian(byte[] bytes)
    {
        var barIds = new BarID[bytes.Length / 4];
        fixed (byte* pBytes = bytes)
        {
            BarID* asIds = (BarID*)pBytes;
            for (int i = 0; i < barIds.Length; i++)
                barIds[i] = asIds[i];
        }
    
        return barIds;
    }
    

    If you know that your code will be used on little endian CPUs (eg. it is meant to be a Windows app), then you don't even need the big endian version:

    private static BarID[] ConvertBigEndian(byte[] bytes)
    {
        var barIds = new BarID[bytes.Length / 4];
        for (int i = 0; i < barIds.Length; i++)
        {
            int offset = i * 4;
            barIds[i] = (BarID)((bytes[offset] << 3) | (bytes[offset + 1] << 2)
                | (bytes[offset + 2] << 1) | bytes[offset + 3]);
        }
    
        return barIds;
    }