2012-10-16 134 views
7

Tôi gặp vấn đề với việc hiểu biểu diễn Kiểu giá trị trong .NET. Mỗi loại giá trị có nguồn gốc từ lớp System.ValueType, điều này có nghĩa là Loại giá trị là một lớp không?Các loại Giá trị trong .NET thực sự hoạt động như thế nào?

Ví dụ, nếu tôi viết:

int x = 5; 

nó có nghĩa là tôi tạo ra một thể hiện của lớp System.Int32 một' viết nó vào biến x ??

+1

[System.ValueType] (http://msdn.microsoft.com/ vi/us/library/system.valuetype.aspx) – Oded

+2

_được nhập từ System.ValueType class_ Đây là một dạng đặc biệt của việc bắt nguồn, không giống như thừa kế. Nó được tích hợp vào Fx. –

+2

Dành cho người đọc trong tương lai: [** Sự thật về các loại giá trị **] (http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx) –

Trả lời

6

Lớp System.ValueType thực sự chỉ là một lớp "meta" và được xử lý nội bộ khác với các lớp thông thường. Các kiểu structs và primitive thừa hưởng System.ValueType, nhưng kiểu đó không thực sự tồn tại trong suốt thời gian chạy, nó chỉ là một cách cho các assembly để đánh dấu một lớp nên được xử lý như một struct kiểu giá trị và nhận các ngữ nghĩa theo giá trị.

Trái với các câu trả lời khác, các loại giá trị không phải lúc nào cũng được phân bổ trên ngăn xếp. Khi chúng là các trường trong một lớp, chúng nằm trên heap giống như phần còn lại của lớp dữ liệu khi đối tượng đó được khởi tạo. Các biến cục bộ cũng có thể được hoisted vào một lớp ngầm khi được sử dụng bên trong vòng lặp hoặc đóng.

+0

Cảm ơn bạn, rất hữu ích –

-1

Loại giá trị không phải là lớp. Đây là các loại nội trang được xây dựng bằng ngôn ngữ và được xử lý bởi .NET CTS (Common Type System). CTS là một thành phần bên trong CLR chịu trách nhiệm xử lý các kiểu giá trị như bool, int, double, float… Khi bạn tạo một đối tượng kiểu giá trị thì nó được tạo trên stack. Khi bạn truyền nó đến một hàm hoặc trả về từ một hàm thì một đối tượng mới sẽ được tạo cho nó trong ram. Nhưng trong trường hợp các kiểu tham chiếu, chỉ tham chiếu đối tượng được truyền và đối tượng mới không được tạo bộ nhớ inm. Có một số loại giá trị do người dùng xác định không có trong đặc tả ngôn ngữ và được xác định bởi người dùng. Các loại giá trị như vậy được kế thừa từ System.ValueType. Ví dụ về loại valuetype này là số phức. Chúng ta có thể tạo kiểu số phức tạp do người dùng xác định bằng cách sử dụng System.ValueType.

+0

Tôi sẽ không downvote vì đây là ngày đầu tiên của bạn trên SO, nhưng xin vui lòng đọc các ý kiến ​​của câu trả lời khác –

+1

Tôi sẽ downvote vì nó sai. Xem http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx để xử lý triệt để các loại giá trị. –

+0

@ThomSmith: Mặc dù ngăn xếp là một chi tiết triển khai, điểm cơ bản là chính xác: các vị trí lưu trữ loại giá trị (bao gồm các thời gian trình biên dịch) không giữ các đối tượng lớp. C# spec có thể cho rằng nội dung của trường 'Int32' thừa hưởng từ' System.Object', nhưng thông số CLI (mô tả cách thế giới của mã được quản lý thực sự hoạt động) làm rõ rằng 'System.Int32' mô tả hai kiểu: một loại đối tượng heap có nguồn gốc từ 'System.Object' và một loại vị trí lưu trữ không phải là một đối tượng. Thông số C# có thể giả vờ khác, nhưng điều đó không đúng. – supercat

0

Bây giờ, có rất nhiều điều để nói về điều đó. Nghiêm túc, có hàng trăm trang về chủ đề này trên mạng, và hầu hết nó đều đốt cháy vấn đề não của tôi với tốc độ đáng báo động.

Những gì tôi thực sự nhớ là, int và Int32 là điều tương tự, và cả hai hành động như một cấu trúc, không phải là một lớp. "int" là lối tắt tới Int32. (Nếu bạn đưa chuột qua một int, các tooltip đọc "struct System.Int32" Có nghĩa là:..

public class BoxedInt 
{ 
    public int x; 

    public BoxedInt(int i) { x = i; } 
} 

public Test() 
{ 
    BoxedInt bi = new BoxedInt(10); 
    Boxed(bi); 
    Console.WriteLine(bi.x); // Returns 11, as any reference type would. 

    int vi = 10; 
    Valued(vi); 
    Console.WriteLine(vi); // Returns 10, because it acts like a struct. (Which it is) 
} 

public void Boxed(BoxedInt i) 
{ 
    i.x++; 
} 

public void Valued(int i) 
{ 
    i++; 
} 
+0

'public void Valued (ref int i)' sẽ trả về 11, bởi vì ...? – AgentFire

+0

Trả lại đóng hộp 11, Trả về có giá trị 10. – LightStriker

+0

Giá trị đóng hộp hoặc nếu bạn muốn, giá trị chứa trong một lớp giống như đang ở trong một hộp. Nếu tôi cho bạn biết nơi hộp tồn tại và bạn thay đổi nội dung của nó, tôi có thể chọn hộp và xem bạn đã thay đổi gì. Đối với điều này, các lớp hoạt động như một hộp, và nó sẽ tồn tại miễn là một nơi nào đó trong mã tham khảo nó. Đối với một giá trị bình thường, tôi có thể cho bạn biết giá trị đó nhưng tôi không thể cung cấp cho bạn. Nếu bạn quyết định rằng nó sẽ thay đổi, tôi không có cách nào để biết rằng trừ khi bạn nói với tôi một cách rõ ràng. Đối với điều này, "i" chỉ tồn tại trong giới hạn của phương thức có giá trị và bị hủy ngay sau khi phương thức được thực hiện. – LightStriker

1

Xem Eric Lippert's article

Nói tóm lại, một loại giá trị được sao chép theo giá trị Value. Các loại là các lớp giống như các kiểu tham chiếu và các thể hiện của các loại giá trị là các đối tượng, 5 là một đối tượng, một thể hiện của System.Int32 (ngắn gọn là int)

Các vấn đề liên quan