繁体   English   中英

使 C# 枚举内存高效?

[英]Make C# enums memory efficient?

根据这个问题,C# 将为Fruits类型的字段分配4 byte大小,是否定义如下:

enum Fruits : byte { Apple, Orange, Banana }

或像这样:

enum Fruits { Apple, Orange, Banana }

我仍然很好奇是否有任何方法可以回避这一点并使 enum 的大小小于4 bytes 我知道这可能不是非常有效或可取的,但知道它是否可能仍然很有趣。

数据对齐(通常在124字节边界上)用于更快地访问数据( int应该在4字节边界上对齐)。

例如(让我使用byteint而不是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 
}

到目前为止,即使在classstruct )中的字段的情况下,您也可以产生效果,例如

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.Appleint 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM