[英]Make C# enums memory efficient?
根據這個問題,C# 將為Fruits
類型的字段分配4 byte
大小,是否定義如下:
enum Fruits : byte { Apple, Orange, Banana }
或像這樣:
enum Fruits { Apple, Orange, Banana }
我仍然很好奇是否有任何方法可以回避這一點並使 enum 的大小小於4 bytes
。 我知道這可能不是非常有效或可取的,但知道它是否可能仍然很有趣。
數據對齊(通常在1
、 2
、 4
字節邊界上)用於更快地訪問數據( int
應該在4
字節邊界上對齊)。
例如(讓我使用byte
和int
而不是enum
來提高可讀性和struct
而不是class
- 這是在sizeof
的幫助下獲取 struct 大小的簡單方法):
// sizeof() == 8 == 1 + 3 (padding) + 4
public struct MyDemo {
public byte A; // Padded with 3 unused bytes
public int B; // Aligned on 4 byte
}
// sizeof() == 8 == 1 + 1 + 2 (padding) + 4
public struct MyDemo {
public byte A; // Bytes should be aligned on 1 Byte Border
public byte B; // Padded with 2 unused bytes
public int C; // Aligned on 4 byte
}
// sizeof() == 2 == 1 + 1
public struct MyDemo {
public byte A; // Bytes should be aligned on 1 Byte Border
public byte B; // Bytes should be aligned on 1 Byte Border
}
到目前為止,即使在class
( struct
)中的字段的情況下,您也可以產生效果,例如
public MyClass {
// 4 Byte in total: 1 + 1 + 2 (we are lucky: no padding here)
private Fruits m_Fruits; // Aligned on 1 Byte border
private byte m_MyByte // Aligned on 1 Byte border
private short m_NyShort; // Aligned on 2 Byte border
}
在集合(數組)的情況下,所有值都是相同的類型,應該以相同的方式對齊,這就是不需要填充的原因:
// Length * 1Byte == Length byte in total
byte[] array = new [] {
byte1, // 1 Byte alignment
byte2, // 1 Byte alignment
byte3, // 1 Byte alignment
...
byteN, // 1 Byte alignment
}
根據這個問題,C#將為 Fruits 類型的字段分配 4 字節大小,無論它是這樣定義的
我會說這不是實際寫在那里的內容。 該帖子描述了堆棧上的內存對齊方式,它似乎也為byte
變量對齊了 4 個字節(可能取決於平台):
byte b = 1;
產生與var fb1 = FruitsByte.Apple
和int i = 1;
相同的IL_0000: ldc.i4.1
指令; (參見sharplab.io )和移動指令中相同的4字節差異(x86上的Core CLR 6.0.322.12309)。
盡管使用相應的枚舉作為結構字段會導致它們與相應的邊框對齊:
Console.WriteLine(Unsafe.SizeOf<C>()); // prints 2
Console.WriteLine(Unsafe.SizeOf<C1>()); // prints 8
public enum Fruits : byte { Apple, Orange, Banana }
public enum Fruits1 { Apple, Orange, Banana }
public struct C {
public Fruits f1;
public Fruits f2;
}
public struct C1 {
public Fruits1 f1;
public Fruits1 f2;
}
數組也會發生同樣的情況,它將分配連續的內存區域而不對齊不同的元素。
有用的閱讀:
對於絕大多數應用程序來說,大小開銷根本不重要。 對於一些專門的應用程序,比如圖像處理,使用常量字節值並進行位操作可能是有意義的。 這也可以是一種將多個值打包到單個字節中的方法,或者將標志位與值組合:
const byte Apple = 0x01;
const byte Orange= 0x02;
const byte Banana= 0x03;
const byte FruitMask = 0x0f; // bits 0-3 represent the fruit value
const byte Red = 0x10;
const byte Green = 0x20;
const byte ColorMask = 0x70; // bits 4-6 represents color
const byte IsValidFlag = 0x80; // bit 7 represent value flag
...
var fruitValue = myBytes[i] & FruitMask;
var IsRed = (myBytes[i] & ColorMask) == Red ;
var isValid = myBytes[i] & IsValidFlag > 0;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.