c# - 可变结构与类?

标签 c# class memory struct mutable

我不确定是使用可变结构还是可变类。 我的程序存储了一个包含很多对象的数组。 我注意到使用一个类会使所需的内存量增加一倍。但是,我希望对象是可变的,而且有人告诉我使用可变结构是邪恶的。 这是我的类型的样子:

struct /* or class */ Block
{
    public byte ID;
    public bool HasMetaData; // not sure whether HasMetaData == false or
                             // MetaData == null is faster, might remove this
    public BlockMetaData MetaData; // BlockMetaData is always a class reference
}

像这样分配大量对象(注意下面的两个代码都运行了 81 次):

// struct
Block[,,] blocks = new Block[16, 256, 16];

使用大约 35 MiB 的内存,同时这样做:

// class
Block[,,] blocks = new Block[16, 256, 16];
for (int z = 0; z < 16; z++)
for (int y = 0; y < 256; y++)
for (int x = 0; x < 16; x++)
    blocks[x, y, z] = new Block();

使用大约 100 MiB 的内存。

总而言之,我的问题如下:

我应该为我的 Block 类型使用结构还是类?实例应该是可变的,并存储一些值和一个对象引用。

最佳答案

首先,如果你真的想节省内存,那么不要使用结构或类。

byte[,,] blockTypes = new byte[16, 256, 16]; 
BlockMetaData[,,] blockMetadata = new BlockMetaData[16, 256, 16];

您想在内存中将类似的东西紧紧地打包。如果可以避免的话,您永远不想在结构中的引用旁边放置一个字节;这样的结构会自动浪费三到七个字节。 在 .NET 中引用必须是字对齐的。

其次,我假设您正在此处构建体素系统。可能有比 3 维数组更好的方式来表示体素,具体取决于它们的分布。如果您要制作大量此类内容,请将它们存储在不可变八叉树 中。通过使用不可变八叉树的 持久性 属性,只要您所代表的宇宙是“ block 状”的,您就可以制作具有 千万亿 体素的立方体结构。也就是说,全世界有很大的相似区域。您需要花费更多的 O(lg n) 时间来访问和更改元素,但您可以使用更多的元素。

第三,“ID”是一种非常糟糕的表示“类型”概念的方式。当我看到“ID”时,我假设该数字唯一地标识该元素,而不是描述它。考虑将名称更改为不那么令人困惑的名称。

第四,有多少元素有元数据?如果具有元数据的元素数量与元素总数相比较小,那么您可能会比引用数组做得更好。考虑一种稀疏数组方法;稀疏数组的空间效率更高。

关于c# - 可变结构与类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9335455/

相关文章:

c# - DataGridView 选中时检查 CheckBox

python - **类(Class)辩护中的夸夸其谈。错误: "__init__() takes exactly 1 argument (2 given)"

memory - 从unity3d中的url异步获取图像

c++ - GMP、C语言内存分配和指针

c++ - 将派生类转换为具有相同公共(public)函数的泛型类类型,同时仍然可以调用派生类的函数

数组和指针版本在内存分配方面的比较

c# - Entity Framework 有mysql,实体没有PK

c# - NPoco:使用表达式表示法更新一些(但不是全部)列

c# - 使用 OpenFileDialog/C#/.Net 保留最后选择的路径

c++ - 3D 顶点类或结构