2016-08-08 2 views
-1

Я пытаюсь написать общий метод, который преобразует массив любого типа в массив байтов.Преобразование любого типа массива в байты [] переменной длины в C#

method definition: 

    public byte[] convert_item_to_bytes(dynamic items) 
    { 
     byte[] bytearr = ?? 
      //I tried blockcopy, but i am not getting the correct number of elements 
      //Buffer.BlockCopy(items, 0, bytearr, 0, items.Length); 

     return bytearr; 
    } 


examples of my method calls: 

     convert_item_to_bytes(new int16[]{0x1234, 0x4567, 0x9574}); 
     convert_item_to_bytes(new int32[]{0x3545, 0x3352, 0x9642, 0x5421}); 
     convert_item_to_bytes(new uint64[]{0x4254, 0x8468}); 
     //etc.... my method calls can also be of float type. 

Я использую динамику в определении, потому что я узнаю тип онлайн во время выполнения.

PS: Я видел еще один пример, который использует BinaryFormatter и MemoryStream. Я не хочу это использовать. (How to convert byte array to any type)

Есть ли другой способ решить эту проблему?

+0

Я заглянул в [BinaryWriter] (https://msdn.microsoft.com/en-us/library/system.io.binarywriter (v = vs.110) .aspx? F = 255 & MSPPError = -2147217396)/[BinaryReader] (https://msdn.microsoft.com/en-us/library/system.io.binaryreader (v = vs.110) .aspx). –

+5

Вы можете ответить на это, если знаете **, как ** вы можете «преобразовать» любой произвольный объект в массив байтов. Посылка as-is совершенно бессмысленна, так как вам придется прибегать к двоичной сериализации, что и есть для BinaryFormatter. Если «любой тип массива» на самом деле означает «любой числовой тип массива», он [становится немного проще] (https://msdn.microsoft.com/en-us/library/system.bitconverter.getbytes (v = vs. 110) .aspx). – CodeCaster

ответ

1

Есть довольно некоторые проблемы с тем, что вы на самом деле спрашиваете, особенно если вы не хотите писать код для каждого типа. К счастью, в BCL не так много числового типа, поэтому вы можете написать все это один раз или даже позволить ему сгенерировать.

очень наивный подход показан ниже:

public static void Main() 
{ 
    int[] intArray = new int[] { 1, 2, 42, }; 

    byte[] intOutput = ConvertToByteArray(intArray, sizeof(int)); 

    for (int i = 0; i < intOutput.Length; i++) 
    { 
     Console.Write("{0:x2} ", intOutput[i]); 
     if ((i + 1) % singleItemSize == 0) 
     { 
      Console.WriteLine(); 
     } 
    } 
} 

private static byte[] ConvertToByteArray<T>(T[] input, int singleItemSize) 
    where T : struct, 
     IComparable, 
     IComparable<T>, 
     IConvertible, 
     IEquatable<T>, 
     IFormattable 
{ 
    var outputArray = new byte[input.Length * singleItemSize]; 

    // Iterate over the input array, get the bytes for each value and append them to the output array. 
    for (int i = 0; i < input.Length; i++) 
    { 
     var thisItemBytes = GetBytes(input[i]); 
     Buffer.BlockCopy(thisItemBytes, 0, outputArray, i * singleItemSize, singleItemSize); 
    } 

    return outputArray; 
} 

private static byte[] GetBytes<T>(T input) 
    where T : struct, 
     IComparable, 
     IComparable<T>, 
     IConvertible, 
     IEquatable<T>, 
     IFormattable 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     return BitConverter.GetBytes(Convert.ToInt32(input)); 
    } 
    else if (typeof(T) == typeof(float)) 
    { 
     return BitConverter.GetBytes(Convert.ToSingle(input)); 
    } 
    else 
    { 
     throw new ArgumentException("T"); 
    } 
} 

Этот вывод (в зависимости от байт вашей системы) следующего:

01 00 00 00 
02 00 00 00 
2a 00 00 00 

И поэтому метод ConvertToByteArray() обеспечивает бесполезный массив из 12 байт с учетом ввода int[] { 1, 2, 42 }. Это бесполезно, потому что вы не знаете, содержит ли этот массив 12 байтов, 6 символов, 3 интервала, 3 поплавки или 3 целых числа без знака.

Помимо этого, существует много проблем с показанным кодом, что, я уверен, может быть упрощено.

Вместо этого вы можете найти другое решение для этой, казалось бы, проблемы XY.

+0

Какую версию C# /. Net вы используете? Единственная причина, о которой я спрашиваю, - это ограничение 'struct' на метод ConvertToByteArray. Я думал, что не будет компилироваться раньше, чем C# 6. – IAbstract

+0

@IAbstract, скомпилированный с использованием IdeOne, C# 5 и .NET 4.5 AFAIK. – CodeCaster

+1

Я проверю (было какое-то время), чтобы увидеть, какая версия у меня могла быть проблемой с ограничением 'struct'. – IAbstract