C# - C Sharp: Iterator


Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên

Giới thiệu

Iterator trong C# được dùng để duyệt qua một danh sách các giá trị của tập hợp. Iterator là một khối mã lệnh trong đó thường dùng đến vòng lặp foreach để tham chiếu liên tiếp tới tập hợp các giá trị. Ví dụ như nếu muốn sắp xếp các giá trị của tập hợp ta cần sử dụng iterator để lấy lần lượt từng giá trị một rồi đem so sánh.

Iterator không phải là một thành phần dữ liệu, nó chỉ là cách truy cập các thành phần, chẳng hạn như là một phương thức (bộ truy cập get chẳng hạn) hoặc một toán tử cho phép ta điều hướng thông qua các giá trị của tập hợp. Iterator sẽ xác định cách mà các giá trị được tạo ra khi vòng lặp foreach truy cập vào các phần tử của tập hợp, và iterator sẽ lưu vết của các phần tử đó, điều này sẽ giúp tăng tốc độ truy cập các giá trị của các phần tử.

Ưu điểm của iterator

· Iterator cung cấp một cách đơn giản và nhanh hơn cách thức duyệt (lặp) trên các giá trị của tập hợp.

· Iterator sẽ giảm đi tính phức tạp bằng việc cung cấp bộ liệt kê cho tập hợp.

· Iterator có thể trả về một số lượng lớn các giá trị.

· Iterator có thể được dùng để định lượng các giá trị và chỉ trả lại những giá trị cần thiết.

· Iterator có thể trả lại những giá trị mà không hề dùng đến bộ nhớ bằng cách tham chiếu đến từng giá trị trong tập hợp.

Thực thi iterator

Iterator có thể được tạo bằng cách thực thi phương thức GetEnumerator() của interface IEnumerator, phương thức này sẽ trả về một tham chiếu của interface này.

Khối iterator sẽ sử dụng từ khoá yield để cung cấp các giá trị cho thể hiện của bộ liệt kê (enumerator) hoặc để kết thúc quá trình lặp, cụ thể, câu lệnh yield return sẽ trả về các giá trị, còn câu lệnh yield break sẽ kết thúc tiến trình lặp. Khi gặp câu lệnh yield return thì vị trí hiện thời sẽ được lưu trữ và lần kế khi iterator được gọi thì việc thực thi sẽ bắt đầu từ vị trí đã được lưu trữ đó. Ví dụ:

using System;
using System.Collections;

namespace Demo
{
  class Department : IEnumerable
  {
    string[] departmentNames = { "Marketing", "Tai chinh", "Cong nghe thong tin", "Hanh chinh nhan su" };
    public IEnumerator GetEnumerator()
    {
      for (int i = 0; i < departmentNames.Length; i++)
      {
        yield return departmentNames[i];
      }
    }
  
    static void Main(string[] args)
    {
      Department objDepartment = new Department();
      Console.WriteLine("Ten cua cac phong ban:");
      foreach (string str in objDepartment)
      {
        Console.WriteLine(str);
      }
    }
  }
}

Trong ví dụ trên, lớp Department thực thi interface IEnumerable, trong lớp có một biến mảng để lưu trữ tên của các phòng ban và thực thi phương thức GetEnumerator() của IEnumerable bên trong có vòng lặp for, vòng lặp này trả về các tên của các phòng ban ứng với mỗi vị trí chỉ số trong biến mảng; khối mã trong phương thức GetEnumerator() chính là sự thể hiện của iterator; phương thức thức Main() tạo một thể hiện của lớp Department và chứa một vòng lặp foreach để hiển thị tên của các phòng ban.

Dưới đây là kết quả thể hiện cho ví dụ trên:

Ten cua cac phong ban:
Marketing
Tai chinh
Cong nghe thong tin
Hanh chinh nhan su

Lưu ý: Khi bắt gặp iterator thì trình biên dịch của C# sẽ gọi các phương thức Current(), MoveNext() và Dispose() (một cách mặc định); những phương thức này được dùng để duyệt các dữ liệu trong tập hợp.

Iterator generic

C# cho phép tạo iterator generic, công việc này được thực hiện bằng cách trả về một đối tượng có kiểu interface generic IEnumerator<T> hoặc IEnumerable<T>. Iterator generic có thể duyệt dữ liệu với kiểu bất kỳ. Ví dụ:

using System;
using System.Collections.Generic;

namespace Demo
{
  class GenericDepartment<T>
  {
    T[] item;
    public GenericDepartment(T[] val)
    {
      item = val;
    }
    public IEnumerator<T> GetEnumerator()
    {
      foreach (T value in item)
      {
        yield return value;
      }
    }
  }
  class GenericIterator
  {
    static void Main(string[] args)
    {
      string[] departmentNames = { "Marketing", "Finance", "Information Technology", "Human Resources" };
      GenericDepartment<string> objGeneralName = new GenericDepartment<string>(departmentNames);
      foreach (string val in objGeneralName)
      {
        Console.Write(val + "\t");
      }
      int[] departmentID = { 101, 110, 210, 220 };
      GenericDepartment<int> objGeneralID = new GenericDepartment<int>(departmentID);
      Console.WriteLine();
      foreach (int val in objGeneralID)
      {
        Console.Write(val + "\t\t");
      }
      Console.WriteLine();
    }
  }
}

Trong ví dụ trên, lớp generic GenericDepartment được tạo với tham số kiểu là T, trong lớp có một biến mảng và một hàm tạo có tham số để khởi tạo giá trị cho các phần tử của mảng; trong lớp GenericDepartment còn có phương thức GetEnumerator() với kiểu trả về là IEnumerator, phương thức này trả lại các phần tử được lưu trong biến mảng thông qua câu lệnh yield return; phương thức Main() trong lớp GenericIterator tạo một thể hiện của lớp GenericDepartment để tham chiếu tới các tên phòng ban khác nhau của mảng; một đối tượng khác của lớp GenericDepartment cũng được tạo và nó tham chiếu tới các ID của các phòng ban của mảng.

Iterator được đặt tên

Iterator có thể được tạo bằng cách tạo một phương thức với tên riêng, phương thức này có kiểu trả về là interface IEnumerable, người ta gọi là iterator được đặt tên. Loại iterator này có thể chấp nhận các đối số mà có thể được dùng để quản lý điểm đầu và điểm cuối của vòng lặp foreach. Kỹ thuật này giúp ta lấy những giá trị theo ý muốn trong tâp hợp.

Sau đây là cú pháp cho kỹ thuật này:

Access_modifier  IEnumerable  Iterator_name(Parameter_list){}

Ví dụ:

using System;
using System.Collections;

namespace Demo
{
  class NamedIterators
  {
    string[] cars = { "Ferrari", "Mercedes", "BMW", "Toyota", "Nissan" };
    public IEnumerable GetCarNames()
    {
      for (int i = 0; i < cars.Length; i++)
      {
        yield return cars[i];
      }
    }
    static void Main(string[] args)
    {
      NamedIterators objIterator = new NamedIterators();
      foreach (string str in objIterator.GetCarNames())
      {
        Console.WriteLine(str);
      }
    }
  }
}

Trong ví dụ trên, lớp NamedIterators bao gồm một biến mảng và phương thức GetCarNames() (đây chính là iterator được đặt tên) có kiểu trả về IEnumerable, vòng lặp for của phương thức duyệt các giá trị trong biến mảng; phương thức Main() tạo một thể hiện của lớp NamedIterators và thể hiện này được dùng trong vòng lặp foreach để hiển thị tên của các xe hơi trong biến mảng.

Kết quả cho ví dụ trên được thể hiện như sau:

Ferrari
Mercedes
BMW
Toyota
Nissan
» Tiếp: Phương thức không tên
« Trước: Tạo và sử dụng generic
Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên
Copied !!!