C# Academy · Lektion

Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering

Send ArraySegment i stedet for arrays: opret vinduer, implementér Skip/Take/Slice, pars headere og payloads, og kopiér kun ved grænserne.

Lektion 2 af 38 trin

Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 2 af 3. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 3 lektioner i alt.

Udsnit over arrays

Mål: Behandl arrays som hukommelsesudsnit.

  • Brug ArraySegment<T> til at sende visninger
  • Byg små hjælpefunktioner som Skip/Take/Slice
  • Fortolk headere og nyttelast uden kopier
  • Kopiér kun ved I/O-grænser

Hjælpefunktioner til Skip/Take/Slice

Opret små hjælpefunktioner som Slice, Skip og Take for at sammensætte udsnit tydeligt.

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]);
  }
}

Kopiér fra udsnit til udsnit

Brug Buffer.BlockCopy til at flytte data mellem udsnit uden at oprette nye arrays.

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
  }
}

Fortolkning af header og nyttelast

Fortolk ud fra forskydning, og opret et udsnit af nyttelasten. Konvertér kun til tekst, når det er nødvendigt.

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));
  }
}

Skrivebeskyttet efter konvention

Skrivebeskyttet adfærd er en konvention i C# 6 med ArraySegment: Du må aldrig ændre data i funktioner, der kun lover at læse.

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);
  }
}

Kopiér ved grænserne

Kopiér kun ved kanten (når data sendes til et andet lag, logføres eller gemmes). Behold de indre trin uden kopiering.

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));
  }
}

Hvorfor udsnit hjælper

Hurtigt tjek: Hvorfor skal du sende ArraySegment til en fortolker i stedet for byte[]?

Opsamling

Opsamling: Brug ArraySegment<T> som et hukommelseslignende udsnit. Sammensæt det med Skip/Take/Slice, fortolk ud fra forskydninger, og kopiér kun, når du er nødt til det.

Gratis at komme i gang

Lær C# med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
93
Lektioner
346

Ofte stillede spørgsmål

Er lektionen “Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering” gratis?

Ja — hele teksten til “Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 3 lektioner i alt.

Hvad lærer jeg i “Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering”?

Send ArraySegment i stedet for arrays: opret vinduer, implementér Skip/Take/Slice, pars headere og payloads, og kopiér kun ved grænserne. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C# Academy?

Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 3.

Hvor lang tid tager lektionen “Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C# Academy-lektion?

Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Grundlæggende Span/ReadOnlySpan (C# 6-emulering)
  2. Emulering af Memory/ReadOnlyMemory: vinduer uden kopiering
  3. String-as-Span-API'er (C# 6-emulering)
← Tilbage til C# Academy