การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก
ส่ง ArraySegment แทนอาร์เรย์: สร้างหน้าต่าง ใช้ Skip/Take/Slice แยกวิเคราะห์ส่วนหัวและข้อมูล และคัดลอกเฉพาะตรงขอบเขต
การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน
หน้าต่างเหนืออาร์เรย์
เป้าหมาย: มองอาร์เรย์เป็นหน้าต่างของหน่วยความจำ
- ใช้ ArraySegment<T> เพื่อส่งมุมมอง
- สร้างตัวช่วยขนาดเล็กสำหรับการข้าม การเลือก และการแบ่งช่วง
- แยกวิเคราะห์ส่วนหัวและข้อมูลเนื้อหาโดยไม่คัดลอก
- คัดลอกเฉพาะที่ขอบเขตการรับส่งข้อมูล
ตัวช่วยข้าม เลือก และแบ่งช่วง
สร้างตัวช่วยขนาดเล็กสำหรับการแบ่งช่วง การข้าม และการเลือก เพื่อประกอบหน้าต่างให้ชัดเจน
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]);
}
}
การคัดลอกจากหน้าต่างหนึ่งไปอีกหน้าต่างหนึ่ง
ใช้เมธอด BlockCopy ของบัฟเฟอร์เพื่อย้ายข้อมูลระหว่างหน้าต่างโดยไม่สร้างอาร์เรย์ใหม่
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
}
}
การแยกวิเคราะห์ส่วนหัวและข้อมูลเนื้อหา
แยกวิเคราะห์โดยใช้ ตำแหน่งเริ่มต้น แล้วสร้าง หน้าต่าง สำหรับข้อมูลเนื้อหา แปลงเป็นข้อความเฉพาะเมื่อจำเป็น
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));
}
}
อ่านอย่างเดียวตามข้อตกลง
ใน C# 6 พฤติกรรมอ่านอย่างเดียวของ ArraySegment เป็น ข้อตกลง: อย่าเปลี่ยนแปลงข้อมูลภายในฟังก์ชันที่รับรองว่าจะอ่านเท่านั้น
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);
}
}
คัดลอกที่ขอบเขต
คัดลอกเฉพาะที่ขอบเขต เช่น เมื่อส่งข้อมูลไปยังอีกชั้นหนึ่ง บันทึกข้อมูล หรือจัดเก็บข้อมูล ให้ขั้นตอนภายในยังคงไม่คัดลอก
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));
}
}
เหตุผลที่หน้าต่างช่วยได้
สรุปทบทวน
สรุปทบทวน: ใช้ ArraySegment<T> เป็นหน้าต่างที่คล้ายหน่วยความจำ ประกอบหน้าต่างด้วยการข้าม การเลือก และการแบ่งช่วง แยกวิเคราะห์ตามตำแหน่งเริ่มต้น และคัดลอกเฉพาะเมื่อจำเป็น
คำถามที่พบบ่อย
บทเรียน “การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก”
ส่ง ArraySegment แทนอาร์เรย์: สร้างหน้าต่าง ใช้ Skip/Take/Slice แยกวิเคราะห์ส่วนหัวและข้อมูล และคัดลอกเฉพาะตรงขอบเขต คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน
บทเรียน “การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม
ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐาน Span/ReadOnlySpan (จำลองใน C# 6)
- การจำลอง Memory/ReadOnlyMemory: หน้าต่างแบบไม่คัดลอก
- API แบบสตริงเป็น Span (จำลองใน C# 6)