Convert Byte array into collection of items of different types I'm recieving UDP messages as byte arrays and depending on details in some of the first byte, I need to convert remaining bytes into a multitude of different possible arrangements of other data types.

These data types are primarily 'uint', 'ushort' and just 'byte' but can be in any order, and there can be any number of them. Each of these items will have a named variable.

I've tried using quite a few different options and am getting close, but feel that the methods I've created are not the best they could be. In places I've wanted to use 'sizeof' but don't want to mark the code as 'unsafe'. I've tried to use the 'params' keyword on the input, but this cannot be in conjunction with 'ref'. I've wanted to pass them with a maximum number of T1, T2, etc. using generics, but realised I can't enumerate these. I'm now passing an array of variables in conjunction with the 'ref' keyword, which means creating the array in memory but only the array gets updated with the changed and not the original variables.

byte[] message = new byte[] { }; //some byte array
ushort item1 = default(ushort);
byte item2 = default(byte);
var argumentArray = new object[] { item1, item2 };
ConvertArray(response, ref argumentArray);


private void ConvertArray(byte[] response, ref object[] items)
{
    int index = 0;
    for (int i = 0; i &lt; items.Length; i++)
    {
        var item = items[i];
        var itemType = item.GetType();
        var itemSize = SizeOf(item.GetType());

        if (itemSize == 0)
        {
            continue;
        }
        else if (itemSize == 1)
        {
            items[i] = response[index];
        }
        else
        {
            var method = typeof(BitConverter).GetMethod($"To{itemType.Name}");
            var returned = method.Invoke(null, new object[] { response, index });
            items[i] = Convert.ChangeType(returned, itemType);
        }

        index = index + itemSize;
     }
}


private int SizeOf(Type type)
{
   switch (type.Name)
   {
       case nameof(UInt16):
           return 2;

       case "Byte":
           return 1;

       default:
           return 0;
   }
}


So this is partially working in that 'argumentArray' is updating with the values from the 'ConvertArray' method, but I'm sure there is a neater way to do this using Types.

Ideally I wouldn't need to create the 'argumentArray' and just pass the items (e.g. Item1 and Item2) directly as arguments to the method.
case nameof(UInt16):
           return 2;

       case "Byte":
           return 1;



Be consistent. nameof is clearly preferable.




private void ConvertArray(byte[] response, ref object[] items)
{
    int index = 0;
    for (int i = 0; i &lt; items.Length; i++)
    {
        var item = items[i];
        var itemType = item.GetType();
        var itemSize = SizeOf(item.GetType());




The last line should use the variable itemType.
The sole point of items seems to be to extract types. So why is the parameter not params Type[] types?





        if (itemSize == 0)
        {
            continue;
        }



Would it be better to throw an exception?




        else if (itemSize == 1)
        {
            items[i] = response[index];
        }



That's a bug waiting to happen in the future when you add support for sbyte.




        {
            var method = typeof(BitConverter).GetMethod($"To{itemType.Name}");
            var returned = method.Invoke(null, new object[] { response, index });
            items[i] = Convert.ChangeType(returned, itemType);
        }



Ugh. I would much rather use T4 to generate the entire method and get rid of the reflection. That would probably also eliminate the need for Sizeof.



If you're using a recent .Net (e.g. .Net Core 2.1) then I think some combination of Span&lt;T&gt; and Memory&lt;T&gt; will do what you want. Over the past year or so, Microsoft has done a lot of work on C# features for byte-level memory manipulation. You can probably create a struct for the contents of the packet and coerce the byte[] into your struct with one or two lines of code.