0Pricing
C# Academy · Lección

Emulación de Memory/ReadOnlyMemory: ventanas sin copias

Pase ArraySegment en lugar de arrays: cree ventanas, implemente Skip/Take/Slice, analice cabeceras y cargas útiles, y copie solo en los límites.

Emulación de Memory/ReadOnlyMemory: ventanas sin copias es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 2 de 3. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 3 lecciones en total.

Ventanas sobre arrays

Objetivo: Trate los arrays como ventanas de memoria.

  • Use ArraySegment<T> para pasar vistas
  • Cree pequeños auxiliares Skip/Take/Slice
  • Analice encabezados y cargas útiles sin copias
  • Copie únicamente en los límites de E/S

Auxiliares Skip/Take/Slice

Cree pequeños auxiliares Slice, Skip y Take para componer ventanas con claridad.

using System;

public static class Seg
{
  public static ArraySegment<T> Slice<T>(ArraySegment<T> s, int start, int count)
  {
    if (start < 0 || count < 0 || start + count > s.Count) throw new ArgumentOutOfRangeException();
    return new ArraySegment<T>(s.Array, s.Offset + start, count);
  }

  public static ArraySegment<T> Skip<T>(ArraySegment<T> s, int n)
  {
    if (n < 0 || n > s.Count) throw new ArgumentOutOfRangeException("n");
    return new ArraySegment<T>(s.Array, s.Offset + n, s.Count - n);
  }

  public static ArraySegment<T> Take<T>(ArraySegment<T> s, int n)
  {
    if (n < 0 || n > s.Count) throw new ArgumentOutOfRangeException("n");
    return new ArraySegment<T>(s.Array, s.Offset, n);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    int[] xs = new int[] { 10, 20, 30, 40, 50 };
    ArraySegment<int> view = new ArraySegment<int>(xs, 1, 3); // 20,30,40
    ArraySegment<int> head = Seg.Take<int>(view, 2);          // 20,30
    ArraySegment<int> tail = Seg.Skip<int>(view, 1);          // 30,40
    Console.WriteLine(head.Array[head.Offset] + "," + head.Array[head.Offset + 1]);
    Console.WriteLine(tail.Array[tail.Offset] + "," + tail.Array[tail.Offset + 1]);
  }
}

Copia de una ventana a otra

Use Buffer.BlockCopy para mover datos entre ventanas sin crear arrays nuevos.

using System;

public static class SegCopy
{
  public static int Copy(ArraySegment<byte> src, ArraySegment<byte> dst)
  {
    int n = src.Count < dst.Count ? src.Count : dst.Count;
    Buffer.BlockCopy(src.Array, src.Offset, dst.Array, dst.Offset, n);
    return n;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    byte[] a = new byte[] { 1, 2, 3, 4, 5, 6 };
    byte[] b = new byte[] { 0, 0, 0, 0, 0, 0 };

    ArraySegment<byte> winA = new ArraySegment<byte>(a, 2, 3); // 3,4,5
    ArraySegment<byte> winB = new ArraySegment<byte>(b, 1, 3); // target

    int copied = SegCopy.Copy(winA, winB);
    Console.WriteLine("Copied: " + copied);
    Console.WriteLine(string.Join(",", b)); // 0,3,4,5,0,0
  }
}

Análisis de encabezado y carga útil

Analice mediante offset y cree una ventana para la carga útil. Conviértala en texto únicamente cuando sea necesario.

using System;
using System.Text;

public static class Parser
{
  // Message layout: [len:2 bytes little-endian][type:1 byte][payload:len bytes]
  public static void Parse(ArraySegment<byte> msg)
  {
    if (msg.Count < 3) throw new ArgumentException("message too short");

    int o = msg.Offset;
    byte[] arr = msg.Array;

    int len = arr[o] | (arr[o + 1] << 8); // ushort little-endian
    byte typ = arr[o + 2];

    ArraySegment<byte> payload = new ArraySegment<byte>(arr, o + 3, len);
    Console.WriteLine("Type=" + typ + " Len=" + len);

    // Materialize only at the boundary (to string for display)
    string text = Encoding.ASCII.GetString(payload.Array, payload.Offset, payload.Count);
    Console.WriteLine("Payload: " + text);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    // Build: len=5 ("Hello"), type=42
    byte[] buf = new byte[3 + 5];
    buf[0] = 5; buf[1] = 0; buf[2] = 42;
    byte[] hello = Encoding.ASCII.GetBytes("Hello");
    Buffer.BlockCopy(hello, 0, buf, 3, 5);

    Parser.Parse(new ArraySegment<byte>(buf, 0, buf.Length));
  }
}

Solo lectura por convención

En C# 6, el comportamiento de solo lectura es una convención con ArraySegment: no modifique nunca los datos dentro de funciones que prometan únicamente leer.

using System;

public static class Checksums
{
  // Treat the segment as "read-only": never write to seg.Array here.
  public static int SumBytes(ArraySegment<byte> seg)
  {
    int end = seg.Offset + seg.Count;
    int total = 0;
    for (int i = seg.Offset; i < end; i++) total += seg.Array[i];
    return total & 0xFF;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    byte[] data = new byte[] { 10, 20, 30, 40, 50 };
    ArraySegment<byte> window = new ArraySegment<byte>(data, 1, 3); // 20,30,40
    int checksum = Checksums.SumBytes(window);
    Console.WriteLine("Checksum = " + checksum);
  }
}

Copiar en los límites

Copie únicamente en el extremo (al enviar datos a otra capa, registrarlos o almacenarlos). Mantenga sin copias los pasos internos.

using System;

public static class Materialize
{
  public static T[] ToArray<T>(ArraySegment<T> s)
  {
    T[] copy = new T[s.Count];
    Array.Copy(s.Array, s.Offset, copy, 0, s.Count);
    return copy;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    int[] data = new int[] { 5, 6, 7, 8, 9 };
    ArraySegment<int> middle = new ArraySegment<int>(data, 1, 3); // 6,7,8
    int[] copy = Materialize.ToArray<int>(middle); // copy at boundary
    Console.WriteLine(string.Join(",", copy));
  }
}

Por qué ayudan las ventanas

Comprobación rápida: ¿Por qué pasar ArraySegment a un analizador en lugar de byte[]?

Repaso

Repaso: Use ArraySegment<T> como una ventana similar a Memory. Componga con Skip/Take/Slice, analice mediante offsets y copie únicamente cuando sea imprescindible.

Preguntas frecuentes

¿La lección «Emulación de Memory/ReadOnlyMemory: ventanas sin copias» es gratis?

Sí — el texto completo de «Emulación de Memory/ReadOnlyMemory: ventanas sin copias» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 3 lecciones en total.

¿Qué aprenderé en «Emulación de Memory/ReadOnlyMemory: ventanas sin copias»?

Pase ArraySegment en lugar de arrays: cree ventanas, implemente Skip/Take/Slice, analice cabeceras y cargas útiles, y copie solo en los límites. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C# Academy?

No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 3.

¿Cuánto tiempo toma la lección «Emulación de Memory/ReadOnlyMemory: ventanas sin copias»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C# Academy?

Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Fundamentos de Span/ReadOnlySpan (emulación de C# 6)
  2. Emulación de Memory/ReadOnlyMemory: ventanas sin copias
  3. APIs de string como Span (emulación de C# 6)
← Volver a C# Academy