Trong bài này chúng ta sẽ tìm hiểu:

  • Khái niệm và cách tạo indexer
  • Tạo indexer chỉ đọc
  • Tạo indexer chỉ ghi
  • Tạo giao diện khai báo indexer
  • Thực thi indexer trong cấu trúc hay lớp thừa kế từ các giao diện

Indexer là gì?

Indexer cho phép các thể hiện của một lớp hay struct được lập chỉ mục giống như các mảng. Khi chúng ta định nghĩa indexer cho một lớp hay struct, lớp hay struct này sẽ ứng xử giống như một mảng – tức là được truy cập thông qua các chỉ số và dấu ngoặc vuông ([]).

Khai báo indexer

Khai báo một indexer giống khai báo một property (xem lại chương VII) tức là cũng sử dụng các bộ truy cập (assessors) là set hay get theo cú pháp sau:


Kiểu giá trị this[int index] {

// bộ truy cập get

get {

// trả về giá trị theo chỉ số index

}

// bộ truy cập set

set {

// khởi tạo giá trị theo chỉ số index

}

}

Khác với khai báo một property, khai báo một indexer không dùng tên mà dùng từ khoá this – chỉ thể hiện của lớp hay struct. Các properties khởi tạo hay nhận một dữ liệu thành viên cụ thể của lớp hay struct, ví dụ:


class Student {

private string name ;

……

// Name property

public string Name {

get {

return name;

}

set {

name = value;

}

}

….

}

Truy cập thuộc tính Name của lớp Student:


Student s = new Student();

s.Name = "Minh";

Console.WriteLine(s.Name);

Các indexers, ngược lại, khởi tạo hay nhận một giá trị cụ thể từ thể hiện của lớp hay struct. Ví dụ tạo indexer cho lớp Student:


class Student {

private string[] namelist = new string[size];

static public int size = 10;
public Student() {

for (int i = 0; i = 0 && index = 0 && index <= size-1 ) {

namelist[index] = value;

}

}

}

...

}

Sử dụng indexer:


Student names = new Student();

names[0] = "Zara";

names[1] = "Riz";

names[2] = "Nuha";

names[3] = "Asif";

names[4] = "Davinder";

names[5] = "Sunil";

names[6] = "Rubic";

for ( int i = 0; i < IndexedNames.size; i++ ) {

Console.WriteLine(names[i]);

}

Kết quả:

Zara

Riz

Nuha

Asif

Davinder

Sunil

Rubic

  1. A.
  2. A.
  3. A.

Theo cú pháp ở trên, indexer chỉ có một tham số là  index và có kiểu dữ liệu là int.Tuy nhiên, C# cho phép indexer có thể có nhiều tham số và mỗi tham số có thể kiểu dữ liệu khác nhau. Điều này được gọi là quá tải indexer (overloaded indexer). Ví dụ sau khai báo  indexer với các tham số có kiểu dữ liệu khác nhau:


class Student {

private string[] namelist = new string[size];

static public int size = 10;

public Student() {

for (int i = 0; i = 0 && index = 0 && index <= size-1 ) {

namelist[index] = value;

}

}

}

public int this[string name] { tạo một indexer khác

get {

int index = 0;

while(index < size) {

if (namelist[index] == name) {

return index;

}

index++;

}

return index;

}

}

...

}

Sử dụng indexer:


Student names = new Student();

names[0] = "Zara";

names[1] = "Riz";

names[2] = "Nuha";

names[3] = "Asif";

names[4] = "Davinder";

names[5] = "Sunil";

names[6] = "Rubic";

//dùng indexer thứ nhất

for (int i = 0; i < IndexedNames.size; i++) {

Console.WriteLine(names[i]);

}

//dùng indexer thứ hai

Console.WriteLine(names["Nuha"]);

Tạo indexer chỉ đọc (read only indexer)

Có thể một indexer chỉ đọc bằng cách chỉ sử dụng get như cú pháp:


Kiểu giá trị this[int index] {

// bộ truy cập get

get {

// trả về giá trị theo chỉ số index

}

}

Tạo indexer chỉ ghi (write only indexer)

Có thể một indexer chỉ ghi bằng cách chỉ sử dụng set như cú pháp:


Kiểu giá trị this[int index] {

// bộ truy cập set

set {

// khởi tạo giá trị theo chỉ số index

}

}

Indexer trong  interface

Có thể khai báo một indexer trong interface như ví dụ sau:


interface IRawInt

{

bool this [ int index ] { get; set; }

}

Thực thi indexer trong struct:

struct RawInt : IRawInt

{

...

public bool this [ int index ]

{

get { ... }

set { ... }

}

...

}

Nếu thực thi indexer từ giao diện trong một lớp chúng ta phải dùng từ khoá virtual:


class RawInt : IRawInt

{

...

public virtual bool this [ int index ]

{

get { ... }

set { ... }

}

...

}

Chúng ta cũng có thể thực thi indexer bằng cách chỉ ra interface cụ thể:


struct RawInt : IRawInt

{

...

bool IRawInt.this [ int index  ]

{

get { ... }

set { ... }

}

...

}

Học C# và WPF >