ArrayList trong C#

Trong hướng dẫn trước chúng ta đã tìm hiểu về hai loại collection trong C# là non-generic collection và generic collection. Trong bài viết này chúng ta sẽ tìm hiểu về ArrayList - đây là non-generic collection đầu tiên trong loạt bài hướng dẫn về Collection trong C#.

ArrayList là một loại non-generic collection trong C#. Nó có thể chứa các phần tử của bất kỳ kiểu dữ liệu nào.

Nó tương tự như một mảng, ngoại trừ việc nó tự động thay đổi kích thước khi bạn thêm các phần tử vào trong nó. Không giống như một mảng, bạn không cần chỉ định kích thước của ArrayList.

Nếu bạn chưa biết generic collection và non-generic collection trong C# là gì thì có thể tham khảo ở bài viết này:

Collection trong C# | Comdy
Collection trong C# là gì? Có những loại collection nào trong C#. Tác dụng và cách sử dụng của từng loại collection.

Sơ đồ sau minh họa hệ thống phân cấp lớp ArrayList.

ArrayList trong C#

Như bạn có thể nhìn thấy từ biểu đồ trên, lớp ArrayList triển khai thực hiện các interface IEnumerable, ICollectionIList. Vì vậy, bạn có thể tạo một đối tượng của lớp ArrayList và gán nó cho bất kỳ biến nào có kiểu dữ liệu là những interface trên.

Tuy nhiên, nếu bạn gán nó cho biến có kiểu dữ liệu là interface IEnumerable hoặc ICollection thì bạn sẽ không thể thêm các phần tử vào ArrayList và truy cập ArrayList theo chỉ mục.

Ví dụ sau minh họa cách khai báo một ArrayList:

ArrayList myArryList = new ArrayList();// Recommended
// or - with some limitations
IList myArryList = new ArrayList();
// or - with some limitations
ICollection myArryList = new ArrayList();
// or - with some limitations
IEnumerable myArryList = new ArrayList();
Khởi tạo ArrayList trong C#

Khuyến nghị  sử dụng cách khai báo ArrayList đầu tiên vì lớp ArrayList có bổ sung một số phương thức mà interface IList không có như AddRange(), BinarySearch(), Repeat(), Reverse()vv

Các thuộc tính và phương thức quan trọng của ArrayList

Dưới đây là các thuộc tính được sử dụng phổ biến của lớp ArrayList trong C#:

Thuộc tính Miêu tả
Capacity Trả về hoặc thiết lập số phần tử mà ArrayList có thể chứa
Count Trả về số phần tử thực sự được chứa trong ArrayList
IsFixedSize Trả về một giá trị xác định ArrayList có kích cỡ cố định hay không
IsReadOnly Trả về một giá trị xác định ArrayList là chỉ đọc
Item Trả về hoặc thiết lập phần tử tại vị trí xác định

Dưới đây là các phương thức được sử dụng phổ biến của lớp ArrayList trong C#:

STT Phương thức
1 public virtual int Add(object value);

Thêm một đối tượng vào phần cuối của ArrayList

2 public virtual void AddRange(ICollection c);

Thêm các phần tử của một ICollection vào phần cuối của ArrayList

3 public virtual void Clear();

Gỡ bỏ các phần tử từ ArrayList đó

4 public virtual bool Contains(object item);

Xác định có hay không một phần tử là nằm trong ArrayList

5 public virtual ArrayList GetRange(int index, int count);

Trả về một ArrayList mà biểu diễn một tập con của các phần tử trong ArrayList nguồn

6 public virtual int IndexOf(object);

Trả về chỉ mục (dựa trên cơ sở 0) của lần xuất hiện đầu tiên của một giá trị trong ArrayList hoặc một phần của nó

7 public virtual void Insert(int index, object value);

Chèn một phần tử vào ArrayList tại chỉ mục đã xác định

8 public virtual void InsertRange(int index, ICollection c);

Chèn một phần tử của một collection vào ArrayList tại chỉ mục đã xác định

9 public virtual void Remove(object obj);

Gỡ bỏ lần xuất hiện đầu tiên của một đối tượng đã xác định tại chỉ mục đã xác định

10 public virtual void RemoveAt(int index);

Gỡ bỏ phần tử tại chỉ mục đã xác định của ArrayList

11 public virtual void RemoveRange(int index, int count);

Gỡ bỏ một dãy phần tử từ ArrayList

12 public virtual void Reverse();

Đảo ngược thứ tự phần tử trong ArrayList

13 public virtual void SetRange(int index, ICollection c);

Sao chép các phần tử của một collection qua một dãy các phần tử trong ArrayList

14 public virtual void Sort();

Sắp xếp các phần tử trong ArrayList

15 public virtual void TrimToSize();

Thiết lập capacity tới số phần tử thực sự trong ArrayList

Thêm các phần tử vào ArrayList

Sử dụng phương thức Add() để thêm một phần tử hoặc phương thức AddRange() để thêm nhiều phần tử từ các collection khác vào một ArrayList.

Ở đây, phần tử có nghĩa là giá trị theo nghĩa đen của kiểu dữ liệu nguyên thủy hoặc không nguyên thủy. Xin lưu ý rằng phương thức  AddRange() chỉ có sẵn trong lớp ArrayList nhưng không có trong interface IList. Vì vậy, nó chỉ có thể được sử dụng với biến kiểu ArrayList.

Tips: Phương thức AddRange() có thể nhận đầu vào là bất kỳ kiểu dữ liệu collection nào triển khai thực hiện interface ICollection, ví dụ như: List, ArrayList, SortedList, Queue, Stack, Hashset, Hashtable, v.v.

Ví dụ sau minh họa thêm phần tử vào ArrayList:

ArrayList arryList1 = new ArrayList();
arryList1.Add(1);
arryList1.Add("Two");
arryList1.Add(3);
arryList1.Add(4.5);

IList arryList2 = new ArrayList()
{
    100, 200
};

//Adding entire collection using ArrayList.AdRange() method.
////Note: IList does not contain AddRange() method.
arryList1.AddRange(arryList2);

Bạn cũng có thể thêm các phần tử ngay khi bạn khởi tạo ArrayList bằng cú pháp sau:

IList arrayList = new ArrayList() { 100, "Two", 12.5, 200 };

ArrayList có thể chứa nhiều giá trị null và trùng lặp.

Truy cập các phần tử trong ArrayList

Các phần tử của ArrayList có thể được truy cập bằng cách sử dụng bộ chỉ mục, giống như một mảng. Tuy nhiên, bạn cần chuyển nó sang kiểu dữ liệu thích hợp hoặc sử dụng từ khóa var khi truy cập nó.

ArrayList myArryList = new ArrayList();
myArryList.Add(1);
myArryList.Add("Two");
myArryList.Add(3);
myArryList.Add(4.5f);

//Access individual item using indexer
int firstElement = (int) myArryList[0]; //returns 1
string secondElement = (string) myArryList[1]; //returns "Two"
int thirdElement = (int) myArryList[2]; //returns 3
float fourthElement = (float) myArryList[3]; //returns 4.5

//use var keyword
var firstElement = myArryList[0]; //returns 1

Sử dụng vòng lặp foreach hoặc vòng lặp for để duyệt ArrayList.

IList myArryList = new ArrayList() { 1, "Two", 3, 4.5F };

foreach (var item in myArryList)
{
    Console.WriteLine(item); 
}
            
// Or
// for (int i = 0 ; i< myArryList.Count; i++)
// {
//     Console.WriteLine(myArryList[i]);
// }

Kết quả khi biên dịch và chạy chương trình:

1
Two
3
4.5

Chèn các phần tử vào ArrayList

Sử dụng phương thức Insert

Sử dụng phương thức  Insert() để chèn một phần tử tại vị trí được chỉ định.

IList myArryList = new ArrayList();
myArryList.Add(1);
myArryList.Add("Two");
myArryList.Add(3);
myArryList.Add(4.5);

myArryList.Insert(1, "Second Item");
myArryList.Insert(2, 100);

foreach (var item in myArryList)
{
    Console.WriteLine(item); 
}

Kết quả khi biên dịch và chạy chương trình:

1
Second Item
100
Two
3
4.5

Sử dụng phương thức InsertRange

Sử dụng phương thức InsertRange() để chèn tất cả các giá trị từ một collection khác vào ArrayList tại vị trí được chỉ định.

Xin lưu ý rằng phương thức InsertRange() chỉ có sẵn trong lớp ArrayList nhưng không có trong interface IList. Vì vậy, nó chỉ có thể được sử dụng với biến kiểu ArrayList.

IList arryList1 = new ArrayList();
arryList1.Add(100);
arryList1.Add(200);

ArrayList arryList2 = new ArrayList();
arryList2.Add(10);
arryList2.Add(20);
arryList2.Add(30);

arryList2.InsertRange(2, arryList1);

foreach(var item in arryList2)
{
    Console.WriteLine(item);
}

Kết quả khi biên dịch và chạy chương trình:

10
20
100
200
30

Xóa các phần tử khỏi ArrayList

Sử dụng phương thức Remove

Sử dụng phương thức Remove() để xóa một phần tử đã chỉ định khỏi ArrayList. Phương thức này sẽ tìm và xóa phần tử đầu tiên có giá trị trùng với tham số truyền vào của phương thức Remove.

IList arryList1 = new ArrayList();
arryList1.Add(100);
arryList1.Add(200);
arryList1.Add(300);

arryList1.Remove(100); //Removes 1 from ArrayList

foreach (var item in arryList1)
{
    Console.WriteLine(item);
}

Kết quả khi biên dịch và chạy chương trình:

200
300

Sử dụng phương thức RemoveAt

Sử dụng phương thức RemoveAt() để xóa một phần tử tại vị trí được chỉ định khỏi ArrayList.

IList arryList1 = new ArrayList();
arryList1.Add(100);
arryList1.Add(200);
arryList1.Add(300);

arryList1.RemoveAt(1); //Removes the first element from an ArrayList

foreach (var item in arryList1)
{
    Console.WriteLine(item);
}

Kết quả khi biên dịch và chạy chương trình:

100
300

Sử dụng phương thức RemoveRange

Sử dụng phương thức RemoveRange() để xóa nhiều phần tử trong ArrayList. Phương thức này sẽ xóa số lượng phần tử được chỉ định bắt đầu từ vị trí được chỉ định được chỉ định trong ArrayList.

Xin lưu ý rằng phương thức RemoveRange() chỉ có sẵn trong lớp ArrayList nhưng không có trong interface IList. Vì vậy, nó chỉ có thể được sử dụng với biến kiểu ArrayList.

ArrayList arryList1 = new ArrayList();
arryList1.Add(100);
arryList1.Add(200);
arryList1.Add(300);

arryList1.RemoveRange(0,2);//Removes two elements starting from 1st item (0 index)

foreach(var item in arryList1)
{
    Console.WriteLine(item);
}

Kết quả khi biên dịch và chạy chương trình:

300

Sắp xếp các phần tử trong ArrayList

Lớp ArrayList có phương thức sắp xếp là Sort()Reverse(). Phương thức Sort() sắp xếp các phần tử theo thứ tự tăng dần. Tuy nhiên, tất cả các phần tử phải có cùng kiểu dữ liệu để nó có thể so sánh với bộ so sánh mặc định nếu không nó sẽ ném ngoại lệ lúc thực thi.

Phương thức Reverse() sẽ đảo ngược thứ tự của tất các phần tử trong ArrayList.

ArrayList arList = new ArrayList();
arList.Add(300);
arList.Add(200);
arList.Add(100);
arList.Add(500);
arList.Add(400);

Console.WriteLine("Original Order:");

foreach(var item in arList)
{
    Console.WriteLine(item);
}

arList.Reverse();
Console.WriteLine("Reverse Order:");

foreach(var item in arList)
{
    Console.WriteLine(item);
}

arList.Sort();
Console.WriteLine("Ascending Order:");

foreach(var item in arList)
{
    Console.WriteLine(item);
}

Kiểm tra các phần tử tồn tại trong ArrayList

Phương thức Contains() được sử dụng để kiểm tra một phần tử có tồn tại trong ArrayList hay không.

IList arList = new ArrayList();
arList.Add(100);
arList.Add("Hello World");
arList.Add(300);

Console.WriteLine(arList.Contains(100)); // true

Sự khác biệt giữa Array và ArrayList

Bảng sau liệt kê sự khác biệt giữa Array và ArrayList trong C#.

Mảng ArrayList
Thuộc namespace System. Thuộc namespace System.Collections.
Khai báo & khởi tạo mảng:
int[] arr = new int[5]
int[] arr = new int[5]{1, 2, 3, 4, 5};
int[] arr = {1, 2, 3, 4, 5};
Khai báo & Khởi tạo ArrayList:
ArrayList arList = new ArrayList();
arList.Add(1);
arList.Add("Two");
arList.Add(false);
Mảng lưu trữ một số phần tử cố định. Kích thước của một mảng phải được chỉ định tại thời điểm khởi tạo. ArrayList tự động phát triển kích thước và bạn không cần chỉ định kích thước khi khởi tạo.
Mảng được định kiểu mạnh. Điều này có nghĩa là một mảng chỉ có thể lưu trữ giá trị của một kiểu dữ liệu cụ thể. ArrayList có thể lưu trữ giá trị của bất kỳ kiểu dữ liệu nào.
Không cần phải ép kiểu khi truy xuất phần tử vì nó được định kiểu mạnh và chỉ lưu trữ một kiểu dữ liệu cụ thể. Các phần tử của ArrayList cần được chuyển thành một kiểu dữ liệu thích hợp trong khi truy xuất. Vì vậy, boxing và unboxing xảy ra.
Thực hiện nhanh hơn ArrayList vì nó được định kiểu mạnh. Thực hiện chậm vì phải thực hiện boxing và unboxing .
Sử dụng lớp Array để thực hiện một số tác vụ khác nhau trên mảng. Bản thân ArrayList có các phương thức tiện ích khác nhau cho các tác vụ khác nhau.

Ở bài viết tiếp theo, chúng tôi sẽ trình bày về SortedList - một non-generic collection:

SortedList trong C# | Comdy
SortedList trong C# là gì? SortedList trong C# dùng để làm gì? Cách sử dụng SortedList trong C#.
Lập Trình C#Lập Trình C# Cơ Bản
Bài Viết Liên Quan:
int[] và int[,] trong C#: Ai nhanh hơn
Trung Nguyen 10/10/2020
int[] và int[,] trong C#: Ai nhanh hơn

Hiểu được sự khác biệt giữa các loại mảng trong C# sẽ giúp bạn chọn cấu trúc dữ liệu chính xác cho mọi trường hợp.

Struct và class trong C#: Ai nhanh hơn
Trung Nguyen 09/10/2020
Struct và class trong C#: Ai nhanh hơn

Trong bài viết này, tôi sẽ so sánh sự khác biệt về hiệu suất giữa struct và class trong C#: Ai nhanh hơn.

Best practice cho performance trong C#
Trung Nguyen 03/10/2020
Best practice cho performance trong C#

Mục tiêu của bài viết này là cung cấp một danh sách không đầy đủ các code mẫu cần tránh, vì chúng rủi ro hoặc performance kém.

Đọc ghi file (File I/O) trong C#
Trung Nguyen 26/04/2020
Đọc ghi file (File I/O) trong C#

Hướng dẫn này sẽ giúp bạn tìm hiểu về đọc ghi file (File I/O) trong C# và sử dụng các lớp tiện ích để đọc ghi file.