Есть ли в гостях конвертировать IListчтобы байтовать [], не перечисляя через список и не добавляя новый байт []? - PullRequest
1 голос
/ 21 февраля 2011

Я понимаю, что могу перечислить через IList, например:

public byte[] ConvertToByteArray(IList<ArraySegment<byte>> list) {
    IList<byte> newList = new List<byte>();
    foreach(var asb in list) {
       for ( int i = asb.Offset; i < (asb.Offset + asb .Count); i++ )  {
           newList.Add(asb.Array[i]);
       }
    }
    return newList.ToArray();
}

, но это кажется довольно уродливым, есть ли лучший способ сделать это?

Ответы [ 2 ]

7 голосов
/ 21 февраля 2011

Это может быть потенциально сложная проблема, потому что ArraySegment на самом деле является только оболочкой представления вокруг исходного массива, и нет ограничения на число ArraySegment s, созданных вокруг массива (который хранится как ссылка, не копия, в свойстве ArraySegment.Array), поэтому вы не можете делать какие-либо трюки, просто извлекая массивы за один раз.

При этом ваш исходный код может быть немного улучшен. буферизация копий. Это предполагает, что вы хотите, чтобы значения в сегментах, которые указывают на одинаковые значения в базовом массиве, были продублированы в массиве результатов.

public byte[] ConvertToByteArray(IList<ArraySegment<byte>> list)
{
    var bytes = new byte[list.Sum (asb => asb.Count)];
    int pos = 0;

    foreach (var asb in list) {
        Buffer.BlockCopy (asb.Array, asb.Offset, bytes, pos, asb.Count);
        pos += asb.Count;
    }

    return bytes;
}

Это повторяет более чем list дважды (чтобы получить общее количество, но для больших ArraySe сегментов, буферизованное копирование является большим выигрышем, чем дополнительная итерация, это потеря, в моем синтетическом тесте). Как всегда, измерьте, если это критичный к производительности путь кода.

0 голосов
/ 21 февраля 2011

Я обнаружил это очень хорошее объяснение вашей проблемы, когда однажды боролся с той же самой проблемой. (http://www.fotia.co.uk/fotia/DN.01.CoVariantGenericList.aspx)

С тех пор я достиг типа кода, который вы, возможно, захотите использовать, создав класс, который наследуется от общего списка, и добавив конструктор, который выполняет итерацию для меня.

public class bytes : List<byte>
{
    public bytes()
    {
    }

    public bytes (IList<ArraySegment<byte>> list)
    {
       for ( int i = 0; i < list.Count; i++ )  
       {
           this.Add(asb.Array[i]);
       }        
    }
}

Тогда в вашем коде вы можете просто:

bytes myList = new bytes(yourIList);

Это не устраняет необходимость конвертации, но скрывает код.

...