1. Trang chủ >
  2. Luận Văn - Báo Cáo >
  3. Báo cáo khoa học >

Chương 9 Array, Indexer, and Collection

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.57 MB, 369 trang )


C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



không được khởi tạo (giá trị "khởi tạo" là null). Sử dụng bất kỳ phần tử nào

của mảng cũng gây lỗi chưa khởi tạo biến.

9.1.3 Truy cập đến những phần tử trong mảng

Để truy cập đến những phần tử trong mảng, ta sử dụng toán tử lấy chỉ mục [].

Cũng giống như C/C++, chỉ mục mảng được tính bắt đầu từ phần tử 0.

Property Length của lớp Array cho biết được kích thước một mảng. Như vậy

chỉ mục của mảng đi từ 0 đến Length - 1. Trong mảng myArray ví dụ trên để

lấy phần tử thứ 2 (có chỉ số là 1) trong mảng, ta viết như sau:

int phan_tu_thu_hai = myArray[1];

9.2 Câu lệnh foreach

foreach là một lệnh vòng lặp, dùng để duyệt tất cả các phần tử của một mảng,

tập hợp (nói đúng hơn là những lớp có cài đặt giao diện IEnumerable). Cú

pháp của foreach nhẹ nhàng hơn vòng lặp for (ta có thể dùng for thay cho

foreach)

foreach (kiểu tên_biến in biến_mảng)

{

khối lệnh

}

Ví dụ 9-12 Sử dụng foreach

using System;

namespace Programming_CSharp

{

// một lớp đơn giản để chứa trong mảng

public class Employee

{

public Employee(int empID)

{

this.empID = empID;

}

public override string ToString()

{

return empID.ToString();

}

private int empID;

private int size;

}

public class Tester

{



76



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



static void Main()

{

int[] intArray;

Employee[] empArray;

intArray = new int[5];

empArray = new Employee[3];

// populate the array

for (int i = 0; i < empArray.Length; i++)

empArray[i] = new Employee(i+10);

foreach (int i in intArray)

Console.WriteLine(i.ToString());

foreach (Employee e in empArray)

Console.WriteLine(e.ToString());

}

}



}



9.2.1 Khởi tạo các phần tử mảng

Ta có thể khởi tạo các phần tử mảng vào thời điểm khai báo mảng, bằng cách

ta cung cấp một danh sách những giá trị của mảng được giới hạn trong hai

dấu ngoặc nhọn { }. C# có thể cung cấp những cú phápngắn gọn như sau:

int[] myIntArray = new int[5] { 2, 4, 6, 8, 10 }

int[] myIntArray = { 2, 4, 6, 8, 10 }

Hai cách trên cho cùng kết quả là một mảng 5 phần tử có giá trị là 2, 4, 6, 8,

10.

9.2.2 Từ khóa params

Đôi lúc có những phương thức ta không biết trước số lương tham số được

truyền vào như: phương thức Main() không thể biết trước số lượng tham số

người dùng sẽ truyền vào. Ta có thể sử tham số là mảng. Tuy nhiên khi gọi

hàm ta phải tạo một biến mảng để làm tham số. C# cung cấp cú pháp để ta

không cần truyền trực tiếp các phần tử của mảng bằng cách thêm từ khóa

params

Ví dụ 9-13 Sử dụng từ khóa params

using System;

namespace Programming_CSharp



77



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



{

public class Tester

{

static void Main( )

{

Tester t = new Tester( );

/**

* cách truyền tham số bằng các phần tử

* không cần phải khởi tạo mảng

* (cú pháp rất tự do)

*/

t.DisplayVals(5,6,7,8);

/**

* Cách truyền tham số bằng mảng

* Mảng phải được tạo sẵn

*/

int [] explicitArray = new int[5]

{1,2,3,4,5};

t.DisplayVals(explicitArray);

}

public void DisplayVals(params int[] intVals)

{

foreach (int i in intVals)

{

Console.WriteLine("DisplayVals {0}",i);

}

}

}

}

Kết quả:

DisplayVals 5

DisplayVals 6

DisplayVals 7

DisplayVals 8

DisplayVals 1

DisplayVals 2

DisplayVals 3

DisplayVals 4

DisplayVals 5



78



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



9.2.3 Mảng nhiều chiều

Ma trận là một ví dụ về mảng hai chiều. C# cho phép khai báo mảng n chiều,

tuy nhiên thông dụng nhất vẫn là mảng một chiều (mảng) và mảng hai chiều.

Ví dụ trong phần này là mảng hai chiều, tuy nhiên đối với n chiều cú pháp

vẫn tương tự.

9.2.3.1 Mảng chữ nhật

Trong mảng chữ nhật (Rectangular array) 2 chiều, chiều thứ nhất là số dòng

và chiều thứ hai là số cột. Số phần tử trong các dòng là như nhau và bằng số

cột (tương tự số phần tử trong các cột là như nhau và bằng số dòng) để khai

báo ta sử dụng cú pháp sau:

type [,] array-name

ví dụ như:

int [,] myRectangularArray;

9.2.3.2 Mảng Jagged

Mảng jagged là loại mảng trong mảng. Loại mảng này thật sự thì chúng chỉ là

mảng một chiều nhưng những phần tử của chúng có khả năng quản lí được

một mảng khác nữa, mà kích thước các mảng này thay đổi tùy theo nhu cầu

của lập trình viên. Ta có thể khai báo như sau:

type [ ] [ ]...

Ví dụ như khai báo một mảng hai chiều với tên là myJaggedArray:

int [ ] [ ] myJaggedArray;

Chúng ta có thể truy cập phần tử thứ 5 của mảng thứ ba bằng cú pháp

myJaggedArray[2][4]

9.2.4 Lớp System.Array

Lớp Array có rất nhiều hàm hữu ích, nó làm cho mảng trong C# "thông minh"

hơn nhiều ngôn ngữ khác. Chúng được hỗ trợ như là các phương thức được

dựng sẵn như trường hợp string. Hai phương thức quan trong nhất của lớp

System.Array là Sort() và Reverse().

9.3 Indexers

Indexer tương tự như Property, tuy có khác nhau một chút về ý nghĩa. Xét

một ví dụ mô phỏng một quyển sách có nhiều chương



79



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



Xây dựng 2 lớp Sách và Chương. Lớp Chương cài đặt bình thường. Với lớp

Sách ta sẽ cài đặt một biến thành viên có kiểu túi chứa. Để đơn giản biến này

có kiểu là một mảng

public class Chuong

{

// Các biến thành viên

string m_sTen;

string m_sNoiDung;

}

public class Sach

{

// biến thành viên

Chuong[] m_dsChuong;



}



// Property

public Chuong[] DsChuong

{

get{ return m_dsChuong; }

}



Cách làm này có vài bất lợi như sau: thứ nhất để lấy nội dung từng chương

chúng ta dùng Property để lấy danh sach chương sau đó duyệt qua mảng để

lấy chương mong muốn. Thứ hai là mỗi chương được định danh bởi tên

chương nên ta mong muốn có cách lấy một chương thông qua tên của nó. Ta

có thể cài đặt một hàm để duyệt qua mảng các chương, nhưng Indexer sẽ giúp

làm việc này.

Ví dụ 9-14 Sử dụng indexer

using System;

using System.Collections;

namespace ConsoleApplication

{

// Cài đặt lớp Chuong

public class Chuong

{

private string m_sTen;

private string m_sNoiDung;

public Chuong()

{

m_sTen = "";



80



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



m_sNoiDung = "";

}

public Chuong(string sTen, string sNoiDung)

{

m_sTen = sTen;

m_sNoiDung = sNoiDung;

}

public string Ten

{

get { return m_sTen; }

set { m_sTen = value; }

}

public string NoiDung

{

get { return m_sNoiDung; }

set { m_sNoiDung = value; }

}

} // hết class Chuong

// Cài đặt lớp Sach

public class Sach

{

private string m_sTen;

private ArrayList m_dsChuong;

public Sach()

{

m_sTen = "";

m_dsChuong = new ArrayList();

}

public Sach(string sTen)

{

m_sTen = sTen;

m_dsChuong = new ArrayList();

}

public string Ten

{

get { return m_sTen; }

set

{

if ( value == null )

throw new ArgumentNullException();



81



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



m_sTen = value;

}



}

// indexer thứ nhất có một tham số kiểu int

public Chuong this[int index]

{

get

{

if ( index < 0 || index > m_dsChuong.Count

- 1 )

return null;

return (Chuong)m_dsChuong[index];

}

set

{

if ( index < 0 || index > m_dsChuong.Count

- 1 )



throw new ArgumentOutOfRangeException();

m_dsChuong[index] = value;



}



}



// indexer thứ hai có một tham số kiểu string

public Chuong this[string tenChuong]

{

get

{

foreach (Chuong chuong in m_dsChuong)

{

if ( chuong.Ten == tenChuong )

{

return chuong;

}

}

return null;

}

}

public int add (Chuong chuong)

{



82



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



if ( chuong == null )

throw new ArgumentNullException();

return m_dsChuong.Add(chuong);



}

}// hết class Sach



class Class

{

static void Main(string[] args)

{

Sach s = new Sach("tlv");

s.add(new Chuong("CS", "Tac gia CS"));

s.add(new Chuong("VB", "Tac gia VB"));

Console.WriteLine(s.Ten);

// dùng indexer thứ nhất

Console.WriteLine(s[0].Ten + ": "+

s[0].NoiDung);

// dùng indexer thứ hai

Console.WriteLine("VB: " +

s["VB"].NoiDung);

}

}



Console.Read();



}



Trước hết quan sát lớp Sach để xem khai báo một indexer

// indexer thứ nhất có một tham số kiểu int

public Chuong this[int index]

public: phạm vi truy xuất của indexer

Chuong: kiếu trả về

int index: kiểu và tên tham số nhận vào

this[...]: bắt buộc để khai báo indexer

Thân hàm Indexer cũng chia thành 2 hàm get và set y hệt như Property.

Indexer cung cấp thêm một hoặc nhiều tham số và cho ta cách sử dụng như sử

dụng một mảng:

// dùng indexer thứ nhất



83



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



Console.WriteLine(s[0].Ten + ": "+

s[0].NoiDung);

// dùng indexer thứ hai

Console.WriteLine("VB: " +

s["VB"].NoiDung);

9.4 Các giao diện túi chứa

.NET Framework cung cấp một số các giao diện chuẩn để tương tác với các

lớp túi chứa hay để cài đặt các lớp túi chứa mới tương thích (có cùng giao

diện) với các lớp chuẩn của .NET Framework. Các giao diện được liệt kê ở

Bảng 9 -8 Các giao diện túi chứa

Bảng 9-8 Các giao diện túi chứa

Giao diện

IEnumerable



Ý nghĩa

Khi một lớp cài đặt giao diện này, đối tượng thuộc

lớp có được dùng trong câu lệnh foreach

ICollection

Được cài đặt bởi tất cả các lớp túi chứa có thành

viên CopyTo(), Count, IsReadOnly(),

IsSyncronize(), SyncRoot()

IComparer

So sánh hai đối tượng trong túi chứa

IList

Dùng bởi các lớp túi chứa truy xuất phần tử thông

qua chỉ mục (số)

IDictionary

Dùng bởi các lớp túi chứa truy xuất phần tử thông

qua quan hệ khóa/giá trị như Hashtabe, StoredList.

IDictionaryEnumerator Cho phép duyệt đối với các túi chứa cài đặt

IDictionary

9.5 Array Lists

Một vấn đề cổ điển trong khi sử dụng lớp Array là kích thước: kích thước một

mảng cố định. Nếu không thể biết trước cần có bao nhiêu phần tử, ta có thể

khai báo quá nhiều (lãng phí) hay quá ích (chương trình có lỗi). ArrayList cài

đãt cấu trúc dữ liệu danh sach liệt kê cho phép cấp phát động các phần tử. Lớp

này cài đặt giao diện IList, ICollection, IEnumerable và có rất nhiều hàm

dùng để thao tác lên danh sách.

IComparable

ArrayList có phương thức Sort( ) giúp chúng ta sắp xếp các phần tử. Điều bắt

buộc là phần tử phải thuộc lớp có cài đặt giao diện IComparable (có duy nhất

một phương thức CompareTo()).



84



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



9.6 Hàng đợi

Hàng đợi (queue) là một túi chứa hoạt động theo cơ chế FIFO (First in first

out - vào trước ra trước). Cũng giống như ta đi xếp hàng mua vé xem phim,

nếu ta vào trước mua vé thì ta sẽ được mua vé trước.

Hàng đợi là một tập hợp tốt cho việc ta sử dụng để quản lí nguồn tài nguyên

có giới hạn. Ví dụ như ta gửi đi những thông điệp đến tài nguyên, mà tài

nguyên thì chỉ có thể giải quyết cho một thông điệp. Do đó chúng ta phải tạo

một hàng đợi những thông điệp để cho tài nguyên có thể dựa vào đó mà xử lí

“từ từ”. Lớp Queue cài đặt túi chứa này.

9.7 Stacks

Stack là túi chứa hoạt động theo cơ chế LIFO (Last in first out - vào sau ra

trước). Hai phương thức cơ bản trong việc thêm hoặc xóa Stack là:Push( ) và

Pop( ). Ngoài ra Stack còn có phương thức Peek( ), tương tự như Pop() nhưng

không xóa bỏ phần tử này.

Các lớp ArrayList, Queue và Stack đều có những phương thức giống nhau

như CopyTo( ) và ToArray( ) dùng để sao chép những phần tử vào trong một

mảng. Trong trường hợp Stack thì phương thức CopyTo( ) sẽ sao chép những

phần tử vào một mảng một chiều đã tồn tại, và nội dung chúng sẽ ghi đè lên

vị trí bắt đầu mà chúng ta đã chỉ định. Phương thức ToArray( ) trả về một

mảng mới với nội dung là nhữngphần tử trong stack.

9.8 Dictionary

Dictionary là tên gọi chung cho các túi chứa lưu trữ các phần tử theo quan hệ

khóa/giá trị. Điều này có nghĩa là tương ứng với một "khóa", ta tìm được một

và chỉ duy nhất một "giá trị" tương ứng.Nói cách khác là một "giá trị" có một

"khóa" duy nhất không trùng với bất kỳ "khóa" của giá trị khác.

Một lớp muốn là một Dictionary thì cài đặt giao diện IDictionary. Lớp

Dictionary muốn được sử dụng trong câu lệnh foreach thì cài đặt giao diện

IDictionaryEnumerator.

Dictionary thường được dùng nhất là bảng băm (Hashtable).

Bảng băm

Hashtable là cấu trúc dữ liệu có mục tiêu tối ưu hóa việc tìm kiếm. .et

Framework cung cấp lớp Hashtable cài đặt cấu trúc dữ liệu này.

Một đối tượng được dùng như "khóa" phải cài đặt hay thừa kế phương thức

Object.GetHashCode() và Object.Equals() (các lớp thư viện .NET Framework



85



C# và .Net Framework



Gvhd: Nguyễn Tấn Trần Minh Khang



hiển nhiên thỏa điều kiện này). Một điều kiện nữa là đối tượng này phải

immutable (dữ liệu các trường thành viên không thay đổi) trong lúc đang là

khóa.



86



Xem Thêm
Tải bản đầy đủ (.doc) (369 trang)

×