ชนิด Enumerable แบบกำหนดเอง
นำ IEnumerable ไปใช้ด้วยตัววนซ้ำ
ชนิด Enumerable แบบกำหนดเอง เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
การสร้าง Enumerable ของคุณเอง
การนำ IEnumerable<T> ไปใช้กับคลาสทำให้คลาสนั้นใช้งานใน foreach ได้ เมื่อผสานกับเมธอดตัววนซ้ำ วิธีนี้ช่วยให้คุณสร้างคอลเลกชันและช่วงข้อมูลแบบกำหนดเองได้ด้วยโค้ดเพียงเล็กน้อย
การนำ GetEnumerator ไปใช้ด้วย yield
วิธีที่ง่ายที่สุดในการนำ IEnumerable<T> ไปใช้ คือเขียน GetEnumerator เป็นตัววนซ้ำโดยใช้ yield return คอมไพเลอร์จะสร้างตัวแจกแจงให้คุณ
using System;
using System.Collections;
using System.Collections.Generic;
public class IntRange : IEnumerable<int>
{
private readonly int _start, _count;
public IntRange(int start, int count) { _start = start; _count = count; }
public IEnumerator<int> GetEnumerator()
{
for (int i = 0; i < _count; i++)
yield return _start + i;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
foreach (var n in new IntRange(5, 4))
Console.WriteLine(n);
}
}เหตุใดจึงมีเมธอด GetEnumerator สองเมธอด
IEnumerable<T> สืบทอด IEnumerable ที่ไม่เป็นแบบทั่วไป ดังนั้นคุณจึงต้องนำไปใช้ทั้งสองแบบ ส่วนแบบไม่เป็นแบบทั่วไปที่ระบุอย่างชัดเจนจะส่งต่อการทำงานไปยังรุ่นแบบทั่วไป
using System;
using System.Collections;
using System.Collections.Generic;
public class Letters : IEnumerable<char>
{
public IEnumerator<char> GetEnumerator()
{
yield return 'x';
yield return 'y';
yield return 'z';
}
// Required because IEnumerable<T> extends IEnumerable
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
foreach (var c in new Letters())
Console.WriteLine(c);
}
}การซ่อนตรรกะที่กำหนดเอง
Enumerable แบบกำหนดเองสามารถซ่อนกฎการสร้างที่ซับซ้อนไว้เบื้องหลังชนิดข้อมูลที่ใช้งานง่าย ในที่นี้คลาสจะส่งคืนลำดับ Fibonacci ตามความยาวที่เลือก
using System;
using System.Collections;
using System.Collections.Generic;
public class Fibonacci : IEnumerable<int>
{
private readonly int _count;
public Fibonacci(int count) { _count = count; }
public IEnumerator<int> GetEnumerator()
{
int a = 0, b = 1;
for (int i = 0; i < _count; i++)
{
yield return a;
int next = a + b; a = b; b = next;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
foreach (var n in new Fibonacci(8))
Console.WriteLine(n);
}
}การห่อหุ้มคอลเลกชันภายใน
Enumerable แบบกำหนดเองมักห่อหุ้มที่จัดเก็บข้อมูลภายใน โดยเปิดให้วนซ้ำได้พร้อมควบคุมวิธีเพิ่มหรือกรองรายการ
using System;
using System.Collections;
using System.Collections.Generic;
public class EvenBag : IEnumerable<int>
{
private readonly List<int> _items = new List<int>();
public void Add(int n) { if (n % 2 == 0) _items.Add(n); }
public IEnumerator<int> GetEnumerator() => _items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
var bag = new EvenBag();
bag.Add(1); bag.Add(2); bag.Add(3); bag.Add(4);
foreach (var n in bag) Console.WriteLine(n);
}
}Enumerable แบบกำหนดเองทำงานร่วมกับ LINQ ได้
ชนิดข้อมูลใดก็ตามที่นำ IEnumerable<T> ไปใช้ จะได้รับความสามารถทั้งหมดของ LINQ ทันที คุณสามารถกรอง แปลงรูป และรวบรวมคอลเลกชันแบบกำหนดเองได้โดยไม่ต้องเขียนความสามารถเหล่านี้เพิ่ม
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class IntRange : IEnumerable<int>
{
private readonly int _start, _count;
public IntRange(int start, int count) { _start = start; _count = count; }
public IEnumerator<int> GetEnumerator()
{
for (int i = 0; i < _count; i++) yield return _start + i;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
var range = new IntRange(1, 10);
Console.WriteLine(range.Where(n => n % 3 == 0).Sum());
}
}แต่ละ foreach จะได้ตัวแจกแจงใหม่
เนื่องจากมีการเรียก GetEnumerator ทุกครั้งที่คุณวนซ้ำ Enumerable แบบกำหนดเองจึงสามารถแจกแจงซ้ำได้ โดยแต่ละรอบจะเริ่มต้นใหม่
using System;
using System.Collections;
using System.Collections.Generic;
public class IntRange : IEnumerable<int>
{
private readonly int _count;
public IntRange(int count) { _count = count; }
public IEnumerator<int> GetEnumerator()
{
for (int i = 1; i <= _count; i++) yield return i;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
var r = new IntRange(3);
foreach (var n in r) Console.Write(n);
Console.WriteLine();
foreach (var n in r) Console.Write(n); // fresh again
Console.WriteLine();
}
}Enumerable แบบกำหนดเองชนิดทั่วไป
ทำให้ Enumerable เป็นชนิดทั่วไปเพื่อให้รองรับชนิดองค์ประกอบใดก็ได้ ในที่นี้ ring แบบเรียบง่ายจะแสดงรายการตามลำดับ โดยเริ่มจากตำแหน่งชดเชยที่เลือก
using System;
using System.Collections;
using System.Collections.Generic;
public class Ring<T> : IEnumerable<T>
{
private readonly T[] _items;
private readonly int _start;
public Ring(T[] items, int start) { _items = items; _start = start; }
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < _items.Length; i++)
yield return _items[(_start + i) % _items.Length];
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
var ring = new Ring<string>(new[] { "a", "b", "c", "d" }, 2);
foreach (var s in ring) Console.WriteLine(s);
}
}Enumerable แบบกำหนดเองที่ทำงานแบบเลื่อนเวลา
เนื่องจาก GetEnumerator เป็นตัววนซ้ำในตัวเอง Enumerable แบบกำหนดเองของคุณจึงทำงานแบบเลื่อนเวลาโดยค่าเริ่มต้น รายการจะถูกสร้างขึ้นเมื่อผู้ใช้ผลลัพธ์ดึงค่าเท่านั้น
using System;
using System.Collections;
using System.Collections.Generic;
public class Squares : IEnumerable<int>
{
private readonly int _count;
public Squares(int count) { _count = count; }
public IEnumerator<int> GetEnumerator()
{
for (int i = 1; i <= _count; i++)
{
Console.WriteLine("computing " + i);
yield return i * i;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
foreach (var n in new Squares(3))
Console.WriteLine("got " + n);
}
}ควรสร้าง Enumerable แบบกำหนดเองเมื่อใด
เลือกใช้ Enumerable แบบกำหนดเองเมื่อการเรียงลำดับการวนซ้ำหรือตรรกะการสร้างเป็นส่วนสำคัญของชนิดข้อมูล เช่น การท่องผ่านต้นไม้ source ข้อมูลแบบแบ่งหน้า หรือลำดับข้อมูลทางคณิตศาสตร์ มิฉะนั้นเมธอดตัววนซ้ำทั่วไปก็เพียงพอ
using System;
using System.Collections;
using System.Collections.Generic;
public class Countdown : IEnumerable<int>
{
private readonly int _from;
public Countdown(int from) { _from = from; }
public IEnumerator<int> GetEnumerator()
{
for (int i = _from; i >= 0; i--) yield return i;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
foreach (var n in new Countdown(5)) Console.WriteLine(n);
}
}ลองทำด้วยตนเอง
สร้าง Enumerable แบบกำหนดเองที่สร้างลำดับข้อมูลเรขาคณิต จากนั้นใช้ LINQ กับลำดับนั้น ชนิดข้อมูลของคุณจะเชื่อมต่อกับระบบทั้งหมดได้โดยตรง
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Geometric : IEnumerable<int>
{
private readonly int _start, _ratio, _count;
public Geometric(int start, int ratio, int count) { _start = start; _ratio = ratio; _count = count; }
public IEnumerator<int> GetEnumerator()
{
int value = _start;
for (int i = 0; i < _count; i++) { yield return value; value *= _ratio; }
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class Program
{
public static void Main()
{
var seq = new Geometric(1, 2, 6);
Console.WriteLine(string.Join(", ", seq));
Console.WriteLine("sum: " + seq.Sum());
}
}ตรวจสอบอย่างรวดเร็ว
ทบทวนข้อกำหนดของ IEnumerable
สรุปทบทวน
Enumerable แบบกำหนดเองนำ IEnumerable<T> ไปใช้ จึงทำงานร่วมกับ foreach และ LINQ ได้
- นำ
GetEnumeratorไปใช้เป็นตัววนซ้ำด้วยyield return - จัดเตรียม
GetEnumeratorแบบไม่เป็นแบบทั่วไปที่ระบุอย่างชัดเจนด้วย - การวนซ้ำแต่ละครั้งจะได้ตัวแจกแจงใหม่
- การวนซ้ำจะทำงานแบบเลื่อนเวลาโดยค่าเริ่มต้น
เรียนรู้ C# ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 93
- บทเรียน
- 346
คำถามที่พบบ่อย
บทเรียน “ชนิด Enumerable แบบกำหนดเอง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ชนิด Enumerable แบบกำหนดเอง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ชนิด Enumerable แบบกำหนดเอง”
นำ IEnumerable ไปใช้ด้วยตัววนซ้ำ คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “ชนิด Enumerable แบบกำหนดเอง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม
ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เมธอดตัววนซ้ำด้วย yield return
- yield break และการสิ้นสุดก่อนกำหนด
- ความหมายของการประเมินค่าแบบขี้เกียจ
- ชนิด Enumerable แบบกำหนดเอง