2012-06-21 7 views
5

Tôi không tìm cách cải thiện hiệu suất hoặc sử dụng bộ nhớ, câu hỏi này hoàn toàn được tạo ra từ sự tò mò.Các loại dữ liệu nhỏ được đóng gói như thế nào trong C#

Main Câu hỏi Với lớp sau các biên dịch C# (Mono + .NET) sẽ gói hai short biến thành 4 byte hoặc họ sẽ tiêu thụ 8 byte (với liên kết)?

public class SomeClass { 
    short a; 
    short b; 
} 

Câu hỏi thứ Nếu câu trả lời cho câu hỏi trên không phải là 4 byte, sẽ đề nghị sau đây thay thế bất kỳ lợi thế (nơi SomeClass được sử dụng với số lượng rất lớn):

// Warning, my bit math might not be entirely accurate! 
public class SomeClass { 
    private int _ab; 

    public short a { 
     get { return _ab & 0x00ff; } 
     set { _ab |= value & 0x00ff; 
    } 
    public short b { 
     get { return _ab >> 8; } 
     set { _ab |= value << 8; } 
    } 
} 
+3

Trình biên dịch C# sẽ không liên quan gì đến nó - nó sẽ là thời gian chạy. –

+0

Khi bạn nói "được sử dụng với số lượng rất lớn" - chúng ta đang nói về bao nhiêu, và chúng được sử dụng như thế nào? Bạn đang tạo một mảng/danh sách/etc trong số này? –

+0

@ReedCopsey Vâng, lý thuyết của ngữ cảnh này sẽ là một danh sách lớn với quyền truy cập thường xuyên vào các mục cụ thể theo chỉ mục. –

Trả lời

5

này phụ thuộc vào thời gian chạy, không phải là trình biên dịch. Bạn có thể ghi đè hành vi mặc định bằng [StructLayout], có thể giúp - mặc dù hành vi mặc định sẽ ổn.

Điều đó đang được nói, nếu giảm thiểu tổng kích thước là yêu cầu tuyệt đối, bạn có thể muốn xem xét struct thay vì class. Khi sử dụng một lớp, mỗi cá thể của lớp sẽ thêm chi phí quan trọng. Giữa syncblk, TypeHandle, vv, cũng như tham chiếu (trong đó trên một hệ thống 64bit là một byte 8 byte) đối tượng dụ sử dụng một số tiền hợp lý của "thêm" bộ nhớ ở trên và vượt ra ngoài hai quần short của bạn. Để biết chi tiết, xem "How the CLR Creates Runtime Objects".

Lưu trữ dữ liệu của bạn được đóng gói vào một tập hợp các loại giá trị có thể tránh điều này hoàn toàn và giữ cho các trường hợp giảm xuống 8 byte mỗi tổng cộng (cộng với phí thu phí). Của couse, điều này thay đổi ngữ nghĩa về cách sử dụng, nhưng nếu bạn chỉ sử dụng hai quần short, điều này sẽ làm giảm lượng chi phí liên quan đến loại hình của bạn, đặc biệt là trên các hệ thống 64bit.

+0

Xin cảm ơn các bạn, có một số câu trả lời tuyệt vời ở đây. Cảm ơn bạn đã liên kết, tôi sẽ đọc qua! –

6

Nó phụ thuộc vào thời gian chạy, như @David_M nói, nhưng bạn có thể ép nó bằng cách sử dụng thuộc tính [StructLayout] có một thành viên Pack mà bạn có thể sử dụng để kiểm soát đóng gói. Hoặc bạn có thể sử dụng [FieldOffset] để đặt các thành viên của cấu trúc theo cách thủ công (thậm chí chồng chéo, đó là cách bạn triển khai các công đoàn trong .NET).

2

Bố cục thực tế phụ thuộc vào thời gian chạy vì những người khác đã nhận xét chủ yếu bởi vì bạn có thể chạy cùng một mã trên nhiều nền tảng.

Và có trong trường hợp nhiều đối tượng tiết kiệm dung lượng. Những gì bạn đang tìm kiếm là LayoutKind (thuộc tính StructLayout). Nó cho phép bạn đóng gói các thành viên như bạn muốn. Ví dụ với Sequential nó sẽ đảm bảo nó được đóng gói chặt chẽ.

[StructLayout(LayoutKind.Sequential)] 
public class SomeClass { 
    short a; 
    short b; 
} 

Để biết thêm thông kiểm tra MSDN- Structlayout