Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Lấy enumerator để duyệt List trong C#

Giới thiệu

Để lấy enumerator (bộ đếm) duyệt qua các phần tử của List<T>, sử dụng phương thức GetEnumerator(). Enumerator cho phép duyệt tuần tự mà không cần biết cấu trúc nội bộ.

Cú pháp

public List<T>.Enumerator GetEnumerator ();

Trả về struct List<T>.Enumerator triển khai IEnumerator<T>.

Ví dụ 1: Duyệt List với GetEnumerator()

using System;
using System.Collections.Generic;

public class Demo {
    public static void Main(String[] args) {
        List list1 = new List();
        list1.Add("One");
        list1.Add("Two");
        list1.Add("Three");
        list1.Add("Four");
        list1.Add("Five");

        Console.WriteLine("Các phần tử trong List1...");
        foreach (string item in list1) {
            Console.WriteLine(item);
        }

        List list2 = new List();
        list2.Add("India");
        list2.Add("US");
        list2.Add("UK");
        list2.Add("Canada");
        list2.Add("Poland");
        list2.Add("Netherlands");

        Console.WriteLine("\nCác phần tử trong List2...");
        List.Enumerator enumerator = list2.GetEnumerator();
        while (enumerator.MoveNext()) {
            string item = enumerator.Current;
            Console.WriteLine(item);
        }

        Console.WriteLine("\nList2 bằng List1? = " + list2.Equals(list1));
    }
}

Đầu ra ví dụ 1

Các phần tử trong List1...
One
Two
Three
Four
Five

Các phần tử trong List2...
India
US
UK
Canada
Poland
Netherlands
List2 bằng List1? = False

Ví dụ 2: Duyệt List lớn hơn

using System;
using System.Collections.Generic;

public class Demo {
    public static void Main(String[] args) {
        List list = new List();
        list.Add("One");
        list.Add("Two");
        list.Add("Three");
        list.Add("Four");
        list.Add("Five");
        list.Add("Six");
        list.Add("Seven");
        list.Add("Eight");
        list.Add("Nine");
        list.Add("Ten");

        Console.WriteLine("Enumerator duyệt qua các phần tử list...");
        List.Enumerator enumerator = list.GetEnumerator();
        while (enumerator.MoveNext()) {
            string item = enumerator.Current;
            Console.WriteLine(item);
        }
    }
}

Đầu ra ví dụ 2

Enumerator duyệt qua các phần tử list...
One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Ten

Cấu trúc Enumerator

public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator {
    public T Current { get; }
    public bool MoveNext();
    public void Reset(); // Không hỗ trợ, ném NotSupportedException
    void IDisposable.Dispose(); // Không làm gì cho List
}

Lưu ý quan trọng

  • foreach tự động gọi GetEnumerator(), MoveNext(), Current, và Dispose(). Khuyến nghị dùng foreach thay vì manual enumerator.
  • Enumerator là struct (value type), tránh allocation heap.
  • Không sửa đổi list (Add/Remove/Clear) khi đang enumerating → ném InvalidOperationException.
  • Reset() không được hỗ trợ trong List.Enumerator.
  • Current chỉ hợp lệ sau khi MoveNext() trả về true.

So sánh foreach vs Manual Enumerator

Đặc điểmforeachManual Enumerator
Cú phápNgắn gọn, dễ đọcVerbose
An toànTự động DisposeCần tự Dispose (dùng using)
Linh hoạtKhó kiểm soát luồngDễ dàng pause/resume, skip, nested loop
Hiệu năngTương đươngTương đương

Khi nào dùng Manual Enumerator?

  • Cần duyệt song song hai list (zip-like).
  • Cần lookahead (xem phần tử tiếp theo không consume).
  • State machine phức tạp, yield return custom.
  • Interop với API yêu cầu IEnumerator.