Если вашим пользователям класса нужны все методы и свойства ** Список, вы должны извлечь из него свой класс. Если они им не нужны, приложите список и создайте обертки для методов, которые действительно нужны пользователям класса.
Это строгое правило, если вы пишете публичный API или любой другой код, который будет использоваться многими людьми. Вы можете игнорировать это правило, если у вас есть крошечное приложение и не более 2 разработчиков. Это сэкономит вам время.
Для маленьких приложений вы также можете выбрать другой, менее строгий язык. Ruby, JavaScript - все, что позволяет вам писать меньше кода.
Для типов примитивов (включая байты), используйте System.Buffer.BlockCopy
вместо [1 119] System.Array.Copy
. Это быстрее.
я синхронизировал каждый из предложенных методов в цикле, выполняемом 1 миллион раз с помощью 3 массивов 10 байтов каждый. Вот результаты:
System.Array.Copy
- 0,2187556 секунды System.Buffer.BlockCopy
- 0,1406286 секунды я увеличил размер каждого массива к 100 элементам и повторно выполнил тест:
System.Array.Copy
- 0,2812554 секунды System.Buffer.BlockCopy
- 0,2500048 секунды я увеличил размер каждого массива к 1 000 элементов и повторно выполнил тест:
Наконец, я увеличил размер каждого массива к 1 миллиону элементов и повторно выполнил тест, выполнив каждый цикл [только 1 159] 4000 раз:
Так, при необходимости в новом массиве байтов используют
byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);
, Но, если можно использовать IEnumerable<byte>
, ОПРЕДЕЛЕННО , предпочитают Concat< LINQ;> метод. Это незначительно медленнее, чем оператор урожая C#, но более кратко и более изящно.
IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);
, Если Вы имеете произвольное число массивов и используете.NET 3.5, можно сделать System.Buffer.BlockCopy
решение более универсальный как это:
private byte[] Combine(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays) {
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
*Note: вышеупомянутый блок требует, чтобы Вы добавляющий следующее пространство имен в вершина для него работали.
using System.Linq;
К точке Jon Skeet относительно повторения последующих структур данных (массив байтов по сравнению с IEnumerable< байт>), я повторно выполнил последний тест синхронизации (1 миллион элементов, 4 000 повторений), добавив цикл, который выполняет итерации по полному массиву с каждой передачей:
точка, ОЧЕНЬ важно понять эффективность и создания и использования из получающейся структуры данных. Просто фокусировка на эффективности создания может пропустить неэффективность, связанную с использованием. Престижность, Jon.
Многие ответы, кажется, мне игнорируют установленные требования:
, Эти два вместе исключают последовательность LINQ байтов - что-либо с yield
собирается лишить возможности получать заключительный размер, не выполняя итерации через целую последовательность.
, Если те не реальны требования, конечно, LINQ мог бы быть совершенно хорошим решением (или IList<T>
реализация). Однако я предположу, что Superdumbell знает то, что он хочет.
(РЕДАКТИРОВАНИЕ: у меня только что была другая мысль. Существует большое семантическое различие между созданием копии массивов и чтением их лениво. Рассмотрите то, что происходит, если Вы изменяете данные в одном из "исходных" массивов после вызова Combine
(или безотносительно) метод, но перед использованием результата - с отложенными вычислениями, то изменение будет видимо. С непосредственной копией это не будет. Различные ситуации призовут, чтобы различное поведение - просто что-то знало.)
Вот мои предложенные методы - которые очень похожи на содержавшихся в некоторых из других ответов, конечно:)
public static byte[] Combine(byte[] first, byte[] second)
{
byte[] ret = new byte[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
public static byte[] Combine(byte[] first, byte[] second, byte[] third)
{
byte[] ret = new byte[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
third.Length);
return ret;
}
public static byte[] Combine(params byte[][] arrays)
{
byte[] ret = new byte[arrays.Sum(x => x.Length)];
int offset = 0;
foreach (byte[] data in arrays)
{
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
offset += data.Length;
}
return ret;
}
, Конечно, "params" версия требует создания массива массивов байтов сначала, который представляет дополнительную неэффективность.
При простой необходимости в новом массиве байтов то используйте следующее:
byte[] Combine(byte[] a1, byte[] a2, byte[] a3)
{
byte[] ret = new byte[a1.Length + a2.Length + a3.Length];
Array.Copy(a1, 0, ret, 0, a1.Length);
Array.Copy(a2, 0, ret, a1.Length, a2.Length);
Array.Copy(a3, 0, ret, a1.Length + a2.Length, a3.Length);
return ret;
}
, С другой стороны, если Вам просто нужен единственный IEnumerable, рассмотрите использование оператора урожая C# 2.0:
IEnumerable<byte> Combine(byte[] a1, byte[] a2, byte[] a3)
{
foreach (byte b in a1)
yield return b;
foreach (byte b in a2)
yield return b;
foreach (byte b in a3)
yield return b;
}
Concat является правильным ответом, но по некоторым причинам handrolled вещь получает большинство голосов. Если бы Вам нравится этот ответ, возможно, Вы хотели бы это более общее решение еще больше:
IEnumerable<byte> Combine(params byte[][] arrays)
{
foreach (byte[] a in arrays)
foreach (byte b in a)
yield return b;
}
, который позволил бы Вам сделать вещи как:
byte[] c = Combine(new byte[] { 0, 1, 2 }, new byte[] { 3, 4, 5 }).ToArray();
Класс memorystream отлично справляется с этой задачей. Я не мог заставить буферный класс работать так же быстро, как поток памяти.
using (MemoryStream ms = new MemoryStream())
{
ms.Write(BitConverter.GetBytes(22),0,4);
ms.Write(BitConverter.GetBytes(44),0,4);
ms.ToArray();
}