Trong lưới:
Thường thì bạn không thể dựa vào loại biến mà một hàm sẽ tiêu thụ, vì vậy bạn cần sử dụng một biến đối tượng kéo dài từ mẫu số chung thấp nhất - trong .Net đây là object
.
Tuy nhiên object
là một lớp và lưu trữ nội dung của nó như một tài liệu tham khảo.
List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value
List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
Trong khi cả hai đều giữ cùng một thông tin, danh sách thứ hai lớn hơn và chậm hơn. Mỗi giá trị trong danh sách thứ hai thực sự là một tham chiếu đến một giá trị object
giữ int
.
Điều này được gọi là đóng hộp vì int
được bao bọc bởi object
. Khi truyền lại, int
nó không được đóng hộp - được chuyển đổi trở lại giá trị của nó.
Đối với các loại giá trị (tức là tất cả structs
), điều này chậm và có khả năng sử dụng nhiều không gian hơn.
Đối với các loại tham chiếu (tức là tất cả classes
), vấn đề này ít hơn nhiều, vì dù sao chúng cũng được lưu trữ dưới dạng tham chiếu.
Một vấn đề nữa với loại giá trị được đóng hộp là không rõ ràng rằng bạn đang xử lý hộp, hơn là giá trị. Khi bạn so sánh hai structs
thì bạn đang so sánh các giá trị, nhưng khi bạn so sánh hai classes
thì (theo mặc định) bạn đang so sánh tham chiếu - tức là đây có phải là cùng một ví dụ không?
Điều này có thể gây nhầm lẫn khi xử lý các loại giá trị được đóng hộp:
int a = 7;
int b = 7;
if(a == b) // Evaluates to true, because a and b have the same value
object c = (object) 7;
object d = (object) 7;
if(c == d) // Evaluates to false, because c and d are different instances
Thật dễ dàng để làm việc xung quanh:
if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals
if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
Tuy nhiên, đó là một điều cần cẩn thận khi xử lý các giá trị được đóng hộp.