TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #1452 1.87K
День 1180. #ЗаметкиНаПолях
Выделяем Подмассивы. Окончание
Начало

Теперь рассмотрим второй способ.
Для него рассмотрим новый сценарий. Допустим, мы создаем модель машинного обучения для благотворительной организации, которая будет предсказывать, сделает ли человек донат, в зависимости от его возраста. У нас есть куча данных, которые мы хотим разбить на две секции: обучающие данные, на которых будет обучаться модель, и тестовые данные, по которым мы будем тестировать модель.
var data = new (int, bool)[] {
(20, true),
(50, true),
(35, false),
(55, true),
(16, false)
};

Заметьте, что в примере у нас всего 5 элементов. В реальной же модели обучения их могут быть миллионы, поэтому выделять новый массив будет очень затратно.

4. Использование ArraySegment<T>
var train = new ArraySegment<(int, bool)>(data, 0, 3);
var test = new ArraySegment<(int, bool)>(data, 3, 2);

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

То же самое можно сделать с помощью метода ArraySegment<T>.Slice():
var all = new ArraySegment<(int, bool)>(data);
var train = all.Slice(0, 3);
var test = all.Slice(3, 2);

Мы создаем ArraySegment, который охватывает весь массив, затем вызываем метод Slice(), который создает ещё один ArraySegment с указанными границами.

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

5. Использование ReadOnlySpan<T> и Span<T>
ReadOnlySpan<T> предоставляет оболочку, которая позволяет только чтение из массива:
var train = new ReadOnlySpan<(int, bool)>(data, 0, 3);
var test = new ReadOnlySpan<(int, bool)>(data, 3, 2);

ReadOnlySpan очень похож на ArraySegment. Он принимает массив, начальный индекс и количество элементов. Мы можем перечислить его, но, если мы попытаемся изменить какой-либо элемент через экземпляр ReadOnlySpan, мы получим ошибку компиляции.

Код, использующий Span<T> и его поведение аналогичны коду с ArraySegment<T>. Их отличие в том, что Span<T> можно использовать не только для массивов. Кроме того, ArraySegment<T> реализует IEnumerable<T> таким образом позволяет вернуть результат как IEnumerable<T>, тогда как ReadOnlySpan<T> и Span<T> возвращают соответствующие типы, хотя оба имеют метод GetEnumerator(), поэтому их также можно перечислить через foreach.

Сравнение быстродействия
На массиве из 10 строк быстродействие выделения подмассива из 5 элементов и их перечисления. Общий вид методов:
public int <Метод>()
{
// получение подмассива указанным методом
var slice = <подмассив>;
var cnt = 0;
foreach (var item in slice)
cnt++;

return cnt;
}
Результаты на картинке ниже.

Источник: https://code-maze.com/csharp-array-slicing/
  • 👍 10
More from @netdeveloperdiary
  1. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  2. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  3. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  4. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  5. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →