List<T> trong C#
Ở trong những hướng dẫn trước chúng ta đã tìm hiểu về các non-generic collection trong C# như: ArrayList, SortedList, Hashtable, Stack, Queue và BitArray.
Bây giờ chúng ta sẽ chuyển sang tìm hiểu về các generic collection trong C# như: List<T>, Dictionary<TKey, TValue>, SortedList<TKey, TValue>, Hashset<T>, Stack<T> và Queue<T>.
Trong hướng dẫn này, chúng ta sẽ tìm hiểu về List<T> – một generic collection được sử dụng rất phổ biến trong C#.
Sơ đồ sau minh họa hệ thống phân cấp của List<T>
.
Như được trình bày trong sơ đồ trên, lớp List<T>
triển khai thực hiện tám interface khác nhau cung cấp các chức năng khác nhau. Do đó, đối tượng List<T>
có thể được gán cho bất kỳ biến nào có kiểu dữ liệu là các interface trên. Tuy nhiên, nên tạo một đối tượng List<T>
và gán nó cho biến kiểu IList<T>
hoặc List<T>
, như ví dụ bên dưới.
List<int> intList = new List<int>();
//Or
IList<int> intList = new List<int>();
Trong ví dụ trên, câu lệnh đầu tiên khai báo biến sử dụng List<T>
, trong khi câu lệnh thứ hai khai báo biến sử dụng IList<T>
.
Lớp List<T>
là một triển khai thực hiện của giao diện IList<T>
. Trong lập trình hướng đối tượng, nên sử dụng interface thay vì sử dụng trực tiếp lớp triển khai thực hiện. Vì vậy, nên sử dụng biến kiểu IList <T> để tạo một đối tượng List<T>
.
Tuy nhiên, lớp List<T>
bao gồm nhiều phương thức hỗ trợ hơn giao diện IList<T>
. Phần tiếp theo sẽ trình bày các thuộc tính và phương thức quan trọng của lớp List<T>:
Các thành viên quan trọng của List<T>
Các thuộc tính quan trọng của List<T>:
Thuộc tính | Miêu tả |
---|---|
Items | Trả về hoặc thiết lập phần tử ở chỉ mục đã chỉ định |
Count | Trả về tổng số phần tử tồn tại trong List<T> |
Các phương thức quan trọng của List<T>:
Phương thức | Miêu tả |
---|---|
Add | Thêm một phần tử vào cuối List<T>. |
AddRange | Thêm các phần tử của một collection được chỉ định vào cuối List<T>. |
BinarySearch | Tìm kiếm phần tử và trả về một chỉ mục của phần tử. |
Clear | Xóa tất cả các phần tử khỏi List<T>. |
Contains | Kiểm tra xem phần tử được chỉ định có tồn tại trong List<T> hay không. |
Find | Tìm phần tử đầu tiên dựa trên biểu thức đã chỉ định. |
Foreach | Duyệt qua một List<T>. |
Insert | Chèn một phần tử vào chỉ mục được chỉ định trong List<T>. |
InsertRange | Chèn các phần tử của bộ sưu tập khác vào chỉ mục được chỉ định. |
Remove | Loại bỏ phần tử đầu tiên của phần tử được chỉ định. |
RemoveAt | Loại bỏ phần tử tại chỉ mục được chỉ định. |
RemoveRange | Loại bỏ tất cả các phần tử phù hợp với biểu thức được cung cấp. |
Sort | Sắp xếp tất cả các phần tử. |
TrimExcess | Thiết lập kích thước List<T> bằng với số phần tử thực tế. |
TrueForALL | Xác định xem tất cả phần tử trong List<T> có khớp với các điều kiện được định nghĩa trong biểu thức hay không. |
Thêm các phần tử vào List<T>
Phương thức Add
Sử dụng phương thức Add()
để thêm một phần tử vào List<T>. Ví dụ sau đây minh họa thêm giá trị vào List<T>:
IList<int> intList = new List<int>();
intList.Add(10);
intList.Add(20);
intList.Add(30);
intList.Add(40);
Console.WriteLine(intList.Count);
IList<string> strList = new List<string>();
strList.Add("one");
strList.Add("two");
strList.Add("three");
strList.Add("four");
strList.Add("four");
strList.Add(null);
strList.Add(null);
Console.WriteLine(strList.Count);
IList<Student> studentList = new List<Student>();
studentList.Add(new Student());
studentList.Add(new Student());
studentList.Add(new Student());
Console.WriteLine(studentList.Count);
Đây là kết quả khi biên dịch và chạy chương trình:
4
7
3
Bạn cũng có thể thêm các phần tử tại thời điểm khởi tạo bằng cú pháp khởi tạo đối tượng như sau:
IList<int> intList = new List<int>() { 10, 20, 30, 40 };
//Or
IList<Student> studentList = new List<Student>()
{
new Student() { Id = 1, Name = "Bill" },
new Student() { Id = 2, Name = "Steve" },
new Student() { Id = 3, Name = "Ram" },
new Student() { Id = 4, Name = "Moin" }
};
Phương thức AddRange
Sử dụng phương thức AddRange()
để thêm tất cả các phần tử của một collection khác.
Ví dụ sau minh họa thêm phần tử vào List<T> sử dụng phương thức AddRange:
IList<int> list1 = new List<int>();
list1.Add(10);
list1.Add(20);
list1.Add(30);
list1.Add(40);
List<int> list2 = new List<int>();
list2.AddRange(list1);
Console.WriteLine(list2.Count);
Đây là kết quả khi biên dịch và chạy chương trình:
4
Lưu ý: Phương thức
AddRange()
sẽ chỉ được áp dụng nếu bạn khởi tạo biến kiểu List<T>. IList<T> không có phương thứcAddRange()
.
Truy cập phần tử trong List<T>
Sử dụng phương thức ForEach
Sử dụng phương thức ForEach để duyệt qua các phần tử của List<T>.
List<int> list = new List<int>() { 10, 20, 30, 40, 50 };
list.ForEach(item => Console.WriteLine(item));
Đây là kết quả khi biên dịch và chạy chương trình:
10
20
30
40
50
Sử dụng vòng lặp foreach
Nếu bạn đã khởi tạo List<T> rồi gắn cho biến kiểu IList<T> thì hãy sử dụng câu lệnh foreach để duyệt các phần tử trong collection như sau:
IList<int> list = new List<int>() { 10, 20, 30, 40 };
foreach (var item in list)
{
Console.WriteLine(item);
}
Đây là kết quả khi biên dịch và chạy chương trình:
10
20
30
40
Truy cập từng phần tử bằng cách sử dụng một bộ chỉ mục:
IList<int> list = new List<int>() { 10, 20, 30, 40 };
int elem = list[1]; // returns 20
Sử dụng thuộc tính Count
để lấy tổng số phần tử trong List<T>.
IList<int> intList = new List<int>() { 10, 20, 30, 40 };
Console.Write("Total elements: {0}", intList.Count);
Đây là kết quả khi biên dịch và chạy chương trình:
Total elements: 4
Sử dụng vòng lặp for
Sử dụng vòng lặp for để duyệt List<T> như hình dưới đây:
IList<int> list = new List<int>() { 10, 20, 30, 40 };
int length = list.Count;
for (int i = 0; i < length; i++)
{
Console.WriteLine(list[i]);
}
Đây là kết quả khi biên dịch và chạy chương trình:
10
20
30
40
Lớp List<T> triển khai thực hiện interface IList<T>, vì vậy List<T> được ép kiểu ngầm định về IList<T>. Hãy xem ví dụ sau:
static void Print(IList<string> list)
{
Console.WriteLine("Count: {0}", list.Count);
foreach (string item in list)
{
Console.WriteLine(item);
}
}
static void Main(string[] args)
{
string[] array = new string[2];
array[0] = "Hello";
array[1] = "World";
Print(array);
List<string> list = new List<string>();
list.Add("Hello");
list.Add("World");
list.Add("from");
list.Add("Comdy");
Print(list);
}
Đây là kết quả khi biên dịch và chạy chương trình:
Hello
World
Hello
World
from
Comdy
Chèn phần tử vào List<T>
Sử dụng phương thức Insert()
để chèn một phần tử vào List<T> tại vị trí đã chỉ định.
IList<int> list = new List<int>() { 10, 20, 30, 40 };
list.Insert(1, 11);// inserts 11 at 1st index: after 10.
foreach (var item in list)
{
Console.Write(item);
}
Đây là kết quả khi biên dịch và chạy chương trình:
10
11
20
30
40
Xóa phần tử khỏi List<T>
Các phương thức Remove()
và RemoveAt()
được sử dụng để xóa phần tử khỏi List<T>
.
Phương thức Remove()
sẽ xóa một phần tử trong List<T> có giá trị trùng với giá trị được chỉ định.
Phương thức RemoveAt()
sẽ xóa phần tử tại vị trí được chỉ định trong List<T>.
IList<int> list = new List<int>(){ 10, 20, 30, 40 };
list.Remove(10); // removes the 10 from a list
list.RemoveAt(2); //removes the 3rd element (index starts from 0)
foreach (var item in list)
{
Console.Write(item);
}
Đây là kết quả khi biên dịch và chạy chương trình:
20
30
Phương thức TrueForAll
TrueForAll()
là một phương thức của lớp List<T>
, nó trả về true nếu biểu thức điều kiện được chỉ định là true, ngược lại là false. Ở đây, biểu thức điều kiện có thể được chỉ định là delegate hoặc biểu thức lambda .
List<int> intList = new List<int>(){ 10, 20, 30, 40 };
bool res = intList.TrueForAll(el => el % 2 == 0);// returns true
Ví dụ sau sử dụng phương thức IsPositiveInt()
làm tham số cho TrueForAll.
static bool IsPositiveInt(int i)
{
return i > 0;
}
static void Main(string[] args)
{
List<int> list = new List<int>() { 10, 20, 30, 40 };
bool res = list.TrueForAll(IsPositiveInt);
}
Truy cập MSDN để biết thêm thông tin về các phương thức & thuộc tính của IList<T> hoặc List<T>.
Những điểm cần nhớ:
- List<T> lưu trữ các phần tử của kiểu dữ liệu đã chỉ định và nó tự động phát triển kích thước.
- List<T> có thể lưu trữ nhiều phần tử null và trùng lặp.
- List<T> có thể được gán cho loại biến kiểu IList<T> hoặc List<T>. Nó cung cấp thêm phương thức trợ giúp hữu ích khi được gán cho biến kiểu List<T>.
- List<T> có thể được truy cập bằng cách sử dụng bộ chỉ mục, phương thức ForEach, câu lệnh lặp for hoặc foreach.
- LINQ có thể được sử dụng để truy vấn List<T>.
- List<T> rất lý tưởng để lưu trữ và truy xuất số lượng lớn các phần tử.
Ở hướng dẫn tiếp theo chúng ta sẽ tìm hiểu về lớp Dictionary<TKey,TValue> trong C#.