
Boxing và Unboxing trong C#
June 12, 2025Trong C#, hai khái niệm boxing và unboxing đóng vai trò quan trọng khi làm việc với kiểu dữ liệu value type và reference type, đặc biệt trong quá trình tương tác với object
hoặc các API làm việc với kiểu tham chiếu.
Boxing là gì?
Boxing là quá trình chuyển đổi một biến value type (như int
, float
, bool
,…) thành reference type, cụ thể là thành kiểu object
. Khi thực hiện boxing, CLR (Common Language Runtime) sẽ bọc giá trị đó bên trong một đối tượng kiểu System.Object
và lưu trữ nó trong bộ nhớ heap.
Nói cách đơn giản, boxing cho phép lưu trữ một giá trị kiểu giá trị vào vùng nhớ được quản lý (managed heap). Đây là một quá trình ngầm định – tức bạn không cần ép kiểu một cách tường minh khi thực hiện boxing.
Ví dụ:
int a = 200;
object o = a; // boxing ngầm định
Trong ví dụ trên, a
là biến kiểu int
(value type) với giá trị 200. Khi gán a
cho object o
, hệ thống sẽ thực hiện boxing: tạo một tham chiếu đối tượng o
trên stack, tham chiếu đến một vùng nhớ trên heap nơi giá trị 200
được lưu trữ.
Bạn cũng có thể thực hiện boxing tường minh, mặc dù điều này không bắt buộc:
int i = 235;
object o = (object)i; // boxing tường minh
Điều quan trọng cần lưu ý là boxing luôn tạo ra một bản sao của giá trị gốc. Do đó, nếu bạn thay đổi biến gốc sau khi boxing, biến đã boxed sẽ không bị ảnh hưởng, và ngược lại.
Unboxing là gì?
Unboxing là quá trình ngược lại: chuyển đổi một reference type (object) đã được boxed trở về value type ban đầu. Đây là quá trình ép kiểu tường minh và phải được thực hiện cẩn thận.
Nói cách khác, unboxing giúp bạn lấy lại giá trị gốc từ một object đã được boxing.
Quá trình unboxing gồm 2 bước:
- Kiểm tra đối tượng được truyền vào có phải là một giá trị đã được boxed.
- Sao chép giá trị đó từ heap trở lại biến value type (stack).
Ví dụ:
int a = 50;
object o = a; // boxing
int b = (int)o; // unboxing
Trong đoạn mã trên, a
là biến kiểu int
với giá trị 50. Sau đó, o
là object nhận giá trị từ a
thông qua boxing. Khi b
được gán (int)o
, giá trị 50 được giải nén (unbox) từ object o
và sao chép về stack.
Lưu ý: Đối tượng phải được boxing trước đó mới có thể unbox thành công. Nếu không, chương trình sẽ ném ra lỗi InvalidCastException
.
Boxing và unboxing tuy là tính năng mạnh mẽ của C# nhưng nó lại gây ảnh hưởng đến hiệu năng do chúng tiêu tốn thời gian xử lý và bộ nhớ, vì nó phải thao tác giữa stack và heap, đồng thời tạo ra các bản sao không cần thiết.
Do đó, lập trình viên nên tránh sử dụng boxing/unboxing khi có thể. Thay vào đó, nên sử dụng generics, nó vừa giúp tránh boxing/unboxing, vừa đảm bảo an toàn kiểu dữ liệu.
Hy vọng qua bài viết này, bạn đã hiểu rõ hơn về cơ chế hoạt động của boxing và unboxing trong C#.
Cảm ơn bạn đã theo dõi!