Ở trong hướng dẫn trước chúng ta đã tìm hiểu về lớp List<T> trong C# - một generic collection trong loạt bài hướng dẫn về Collection trong C#. List<T> là một danh sách các phần tử được định kiểu mạnh được sử dụng rất phổ biến trong lập trình C#. Bạn có thể tìm hiểu List<T> ở link dưới đây nếu như chưa xem:
Lớp Dictionary<TKey, TValue>
trong C# giống như một cuốn từ điển tiếng Anh. Từ điển tiếng Anh là một tập hợp các từ và định nghĩa của chúng, thường được liệt kê theo thứ tự alphabet với một hoặc nhiều ngôn ngữ cụ thể. Theo cùng một cách, Dictionary trong C# là một tập hợp các khóa và giá trị, trong đó khóa giống như từ và giá trị giống như định nghĩa.
Lớp Dictionary<TKey, TValue>
là một generic collection trong namespace System.Collection.Generics. Trong đó TKey biểu thị kiểu dữ liệu của khóa và TValue là kiểu dữ liệu của giá trị.
Sơ đồ sau minh họa hệ thống phân cấp lớp Dictionary<TKey, TValue>
.
Một đối tượng Dictionary có thể được gán cho một biến kiểu IDictionary<Tkey, TValue>
hoặc Dictionary<TKey, Tvalue>
.
IDictionary<int, string> dict = new Dictionary<int, string>();
//or
Dictionary<int, string> dict = new Dictionary<int, string>();
Trong ví dụ trên, chúng tôi đã chỉ định kiểu dữ liệu cho khóa và giá trị khi khai báo một đối tượng từ điển. Đối tượng từ điển có tên dict
có kiểu dữ liệu của khóa là int
và kiểu dữ liệu cho giá trị là string
. Bạn có thể sử dụng bất kỳ kiểu dữ liệu C# hợp lệ nào cho các khóa và giá trị.
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, sử dụng interface IDictionary<TKey, TValue>
để khởi tạo một đối tượng từ điển.
Lưu ý: Từ điển không cho phép các khóa trùng lặp hoặc null, nhưng giá trị có thể trùng lặp hoặc null. Các khóa phải là duy nhất nếu không nó sẽ ném ngoại lệ lúc thực thi.
Các thuộc tính quan trọng của Dictionary:
Thuộc tính | Miêu tả |
---|---|
Count | Trả về tổng số phần tử tồn tại trong Dictionary<TKey, TValue>. |
IsReadOnly | Trả về một giá trị cho biết liệu Dictionary<TKey, TValue> có ở chế độ chỉ đọc hay không. |
Item | Trả về hoặc thiết lập phần tử với khóa được chỉ định trong Dictionary<TKey, TValue>. |
Keys | Trả về danh sách các khóa của Dictionary<TKey, TValue>. |
Values | Trả về danh sách các giá trị trong Dictionary<TKey, TValue>. |
Các phương thức quan trọng của Dictionary:
Phương thức | Miêu tả |
---|---|
Add | Thêm một phần tử vào Dictionary. |
Add | Thêm một cặp khóa-giá trị vào Dictionary<TKey, TValue>. |
Remove | Xóa phần tử xuất hiện đầu tiên được chỉ định ra khỏi Dictionary<TKey, TValue>. |
Remove | Xóa phần tử với khóa được chỉ định. |
ContainsKey | Kiểm tra xem khóa được chỉ định có tồn tại trong Dictionary<TKey, TValue> không. |
ContainsValue | Kiểm tra xem giá trị được chỉ định có tồn tại trong Dictionary<TKey, TValue> không. |
Clear | Xóa tất cả các phần tử khỏi Dictionary<TKey, TValue>. |
TryGetValue | Trả về true và gán giá trị với khóa được chỉ định, nếu khóa không tồn tại thì trả về false. |
Sử dụng phương thức Add()
để thêm cặp khóa-giá trị vào từ điển.
IDictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");
IDictionary có nạp chồng phương thức Add(). Nó chấp nhận struct KeyValuePair<TKey, TValue>
như là một tham số đầu vào.
Tips: Kiểm tra xem một từ điển đã lưu trữ khóa được chỉ định trước khi thêm cặp khóa-giá trị.
Ví dụ sau minh họa về thêm phần tử vào Dictionary:
IDictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(new KeyValuePair<int, string>(1, "One"));
dict.Add(new KeyValuePair<int, string>(2, "Two"));
//The following is also valid
dict.Add(3, "Three");
Từ điển cũng có thể được khởi tạo bằng cú pháp khởi tạo đối tượng như dưới đây.
IDictionary<int, string> dict = new Dictionary<int, string>()
{
{1,"One"},
{2, "Two"},
{3,"Three"}
};
Các phần tử của từ điển có thể được truy cập bằng nhiều cách, ví dụ: sử dụng vòng lặp foreach hoặc vòng lặp for.
Sử dụng vòng lặp foreach hoặc for để duyệt qua tất cả các phần tử của từ điển. Từ điển lưu trữ các cặp khóa-giá trị. Vì vậy, bạn có thể sử dụng kiểu KeyValuePair <TKey, TValue> hoặc một biến var trong vòng lặp foreach như dưới đây.
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{1,"One"},
{2, "Two"},
{3,"Three"}
};
foreach (KeyValuePair<int, string> item in dict)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
Đây là kết quả khi biên dịch và chạy chương trình:
Key: 1, Value: One
Key: 2, Value: Two
Key: 3, Value: Three
Sử dụng cho vòng lặp for để truy cập tất cả các phần tử. Sử dụng thuộc tính Count của từ điển để lấy tổng số phần tử trong từ điển.
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{1,"One"},
{2, "Two"},
{3,"Three"}
};
for (int i = 0; i < dict.Count; i++)
{
Console.WriteLine("Key: {0}, Value: {1}",
dict.Keys.ElementAt(i),
dict[dict.Keys.ElementAt(i)]);
}
Đây là kết quả khi biên dịch và chạy chương trình:
Key: 1, Value: One
Key: 2, Value: Two
Key: 3, Value: Three
Từ điển có thể được sử dụng như một mảng để truy cập các phần tử riêng lẻ của nó. Chỉ định khóa (không phải chỉ mục) để lấy giá trị trong từ điển bằng cách sử dụng bộ chỉ mục như một mảng.
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{ 4, "Four" },
{ 2, "Two" },
{ 3, "Three" }
};
Console.WriteLine(dict[4]); //returns Four
Console.WriteLine(dict[2]); // returns Two
Đây là kết quả khi biên dịch và chạy chương trình:
Four
Two
Lưu ý: Indexer lấy khóa làm tham số. Nếu khóa được chỉ định không tồn tại thì sẽ ném ra ngoại lệ KeyNotFoundException.
Nếu bạn không chắc chắn về khóa thì hãy sử dụng phương thức TryGetValue()
. Phương thức TryGetValue()
sẽ trả về false nếu không tìm thấy khóa thay vì ném ngoại lệ.
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{ 4, "Four" },
{ 2, "Two" },
{ 3, "Three" }
};
string result;
if(dict.TryGetValue(1, out result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("Could not find the specified key.");
}
Đây là kết quả khi biên dịch và chạy chương trình:
Could not find the specified key.
Từ điển có nhiều phương thức khác nhau để xác định xem một phần tử hoặc khóa được chỉ định có tồn tại trong từ điển hay không.
Sử dụng phương thức ContainsKey()
để kiểm tra xem một khóa được chỉ định có tồn tại trong từ điển hay không.
Sử dụng phương thức Contains()
để kiểm tra xem cặp Khóa và Giá trị được chỉ định có tồn tại trong từ điển hay không.
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{4, "Four"},
{2, "Two"},
{3, "Three"}
};
dict.ContainsKey(1); // returns false
dict.ContainsKey(4); // returns true
dict.Contains(new KeyValuePair<int,string>(2,"Two")); // returns true
Một nạp chồng của phương thức Contains()
lấy IEqualityComperer làm tham số thứ hai. Một phiên bản của IEqualityComparer được sử dụng khi bạn muốn tùy chỉnh biểu thức so sánh.
Hãy xem ví dụ sau đây về một từ điển lưu trữ các đối tượng Student.
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
class StudentDictionaryComparer : IEqualityComparer<KeyValuePair<int,Student>>
{
public bool Equals(KeyValuePair<int, Student> x, KeyValuePair<int, Student> y)
{
return x.Key == y.Key &&
(x.Value.Id == y.Value.Id) &&
(x.Value.Name == y.Value.Name);
}
public int GetHashCode(KeyValuePair<int, Student> obj)
{
return obj.Key.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
IDictionary<int, Student> studentDict = new Dictionary<int, Student>()
{
{ 1, new Student(){ Id =1, Name = "Bill"}},
{ 2, new Student(){ Id =2, Name = "Steve"}},
{ 3, new Student(){ Id =3, Name = "Ram"}}
};
Student std = new Student() { Id = 1, Name = "Bill" };
KeyValuePair<int, Student> elementToFind = new KeyValuePair<int, Student>(1, std);
bool result = studentDict.Contains(elementToFind, new StudentDictionaryComparer()); // returns true
Console.WriteLine(result);
}
}
Đây là kết quả khi biên dịch và chạy chương trình:
true
Trong ví dụ trên, chúng tôi đã sử dụng StudentDictionaryComparer triển khai thực hiện interface IEqualityComparer để so sánh các đối tượng Student trong từ điển. Bộ so sánh mặc định sẽ chỉ hoạt động với các kiểu dữ liệu nguyên thủy.
Sử dụng phương thức Remove()
để xóa một phần tử hiện có khỏi từ điển. Phương thức Remove()
có hai nạp chồng phương thức, một phương thức chấp nhận một khóa và một phương thức khác chấp nhận struct KeyValuePair<TKey,TValue> làm tham số.
Ví dụ sau minh họa xóa phần tử trong Dictionary sử dụng phương thức Remove với khóa là tham số:
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{1,"One"},
{2, "Two"},
{3,"Three"}
};
dict.Remove(1); // removes the item which has 1 as a key
Với phương thức Remove()
sử dụng KeyValuePair<TKey,TValue> làm tham số thì cả Khóa và Giá trị chỉ định phải khớp thì mới có thể xóa một phần tử. Ví dụ sau sẽ không xóa bất kỳ phần tử nào:
// removes nothing because value Two1 is not matching
dict.Remove(new KeyValuePair<int, string>(2, "Two1"));
Sử dụng generic collection SortedDictionary nếu bạn muốn sắp xếp các phần tử trong từ điển dựa trên khóa.
Những điểm cần nhớ:
ContainsKey()
.TryGetValue()
để lấy giá trị của khóa để tránh các ngoại lệ khi thực thi có thể xảy ra.Ở hướng dẫn tiếp theo chúng ta sẽ tìm hiểu về SortedList<TKey, TValue> - cũng là một generic collection như Dictionary<Tkey, TValue>, cũng lưu trữ các cặp khóa - giá trị.
Bạn sẽ tìm hiểu về Garbage Collector (GC) của .NET quản lý việc cấp phát và giải phóng bộ nhớ cho ứng dụng của bạn.
Trong bài viết này, chúng ta sẽ tìm hiểu về Common Language Runtime (CLR) là gì? Cách biên dịch và chạy ứng dụng được viết bằng C#.
Cung cấp cho bạn một cái nhìn tổng quan về .NET Framework, để hiểu rõ các thành phần và kiến trúc của .NET Framework.
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.