提问人:Feri 提问时间:1/24/2017 更新时间:2/1/2017 访问量:165
c语言中的legal(?)可变结构体大小写#
legal(?) mutable struct case in c#
问:
我读过很多关于 c# 中结构体可变性的文章。大多数词都说可变结构是邪恶的。我明白为什么了。 但是我有一个可变结构似乎是合法的情况。当然,我面临着围绕结构可变性的问题。
比如说,我有一个简单的结构,在GIS编辑器应用程序中是这样:
enum CoordinateSystem : byte { .... } // coordinate system types
struct Vertex
{
float m_x; // m_ is the original value of coordinate, it needs to be kept
float m_y;
float c_x; // c_ is a cache of the result of expensive coordinate transformation
float c_y;
CoordinateSystem cachedSystem; // the current coordinate system type in c_x and c_y
public float x { get {...} set {...}} // properties are for accessing values outside of struct
public float y { get {...} set {...}} // and transforming m_x,m_y into c_x,c_y if necessary
}
属性用于从外部访问坐标。从外部单例类中,结构体可以知道访问 x 和 y 属性时需要什么坐标系。如有必要,get 属性将按需转换m_x和m_y,除了返回值外,它还将结果存储在 c_x 和 c_y 中,以便进一步访问。当然,缓存是必要的,因为坐标转换非常昂贵。使用缓存时,只有第一次访问会很慢,并且同一坐标系中的所有进一步访问都是“即时”的。
顶点位于 List 中,因此基本上长度为 10000 的顶点列表在 List 中被分配为 Vertex[10000]。
显然,问题在于从列表中访问(退出)顶点会返回存储在列表中的结构体副本<>因此转换后的缓存不起作用,因为它将结果存储在短期副本中,而不是存储在列表本身<>。
我不想将 Vertex 更改为类,因为它会(在 64 位运行时上)分配 10000*8 字节作为一个块的引用,在 10000 个块中分配 10000 * 17 字节,这大约是 + 1/3 内存和 10000 倍分配的块数。(我知道这是一个粗略的计算,因为对齐,...... 这是关于一个顶点列表,我有一万个顶点列表,所以上课会浪费很多内存。
我想对外部访问器保持转换透明,因为 Vertex 是多次引用的应用程序中的核心类型。另一个原因是只有顶点知道坐标系,所有其他部分都把 Vertex.x 和 Vertex.y 看作是“数字”,仅此而已。这样,x 和 y 属性应该会进行转换。
问题是:解决这个问题的正确方法是什么?
(请不要将这个问题视为基于意见。这不是其中之一。考虑到申请的目的,我对基于事实的答案感兴趣。
答:
正如 Ivan Stoyev 告诉我们的那样,“数组,这是目前唯一允许通过索引器改变结构元素的集合结构”。 而 List<> 使用数组。
所以我选择了一个肮脏的、应受谴责的、不堪称典范的和邪恶的解决方案,我预见到反对票......但我必须有一个适合内存中千兆字节数据的解决方案,并且不需要更改太多代码。
我修改了 List<> 类的索引器,以在访问列表元素时更改(重新计算)位于存储数组中的结构的缓存部分。
不幸的是,List<> 的存储数组是私有的,不受保护,无法通过继承访问它。因此,我以一种更恶魔的方式走得更远:从 referencesource 中,我复制了 List 源代码的必要部分<>并且(当然,使用不同的名称)最后我有一个具有 List 功能的新类<>但能够在访问索引器时更新内容。
同样,这是一个任何人都不应该遵循的解决方案。 但它效果很好......
评论
List<T>
IList<T>
AccessElement<U>(int index, ActionByValueRefRef<int,T,U> proc, ref U extraValue)
proc(index, ref listItem[index], ref extraValue)
extraValue
下一个:与 ref 传递的参数进行互操作
评论
CoordinateSystem
CoordinateSystem
struct
ref returns
List<T>