如何在.NET中创建Value Type集合?

时间:2015-11-12 10:28:04

标签: c# .net arrays collections f#

我的应用程序的基本构建块类型分解为一个类型(类或结构),其中包含一些标准值类型(int,bool等)和一些标准值类型的数组类型,其中将有一个小的(但未知)集合中的元素数量。

鉴于我有上述构建块的许多实例,我想通过使用数组/集合作为值类型而不是标准引用类型来限制我的基本类型的内存使用。部分问题是我的标准用法是让数组中包含零个,一个或两个元素,并且在这种情况下数组引用类型的开销是禁止的。

我有经验观察并且研究证实,数组包装器本身在每个实例中引入了不需要的(在我看来,在这种情况下)开销。

如何在.NET中将集合设置为值类型/结构?

附注:有趣的是,默认情况下,Apple的Swift语言将数组作为值类型。

优先评论

我完全清楚上面是使用.NET框架的非标准方式,并且是非常糟糕的做法等等......所以没有必要对这种效果进行评论。我真的只想知道如何实现我的要求。

2 个答案:

答案 0 :(得分:1)

The fixed keyword referenced in the docs seems to be what you're looking for. It has the same constraints on types as structs do, but it does require unsafe.

 internal unsafe struct MyBuffer
{
    public fixed char fixedBuffer[128];
}

If you wanted to also have a fixed array of your struct it would be more complicated. fixed only supports the base value types, so you'd have to drop into manual memory allocation.

答案 1 :(得分:1)

来自DirectBufferBufferPool的各种想法可以发挥作用。

如果使用缓冲池,那么在内存中修复缓冲区不是一个大问题,因为缓冲区实际上是长期存在的,并且不会影响GC压缩,就像在没有池的情况下修复每个新的byte[]一样。

DirectBuffer使用flyweight模式并增加很少的开销。您可以使用指针直接读/写任何blittable结构。除了SBE之外,据我所知,Flatbuffers和Cup'n Proto也使用这种方法。在链接的实现中,您应该更改委托,以便它将丢弃的byte[]返回到池中。

如果您需要与本机代码互操作或通过网络发送数据,此类解决方案的巨大优势是零拷贝。此外,您可以分配单个缓冲区并以类似ArraySegment的方式处理偏移量/长度。

<强>更新

我重新阅读了这个问题,并意识到它特别是关于集合作为价值类型。然而,主要的理由似乎是内存压力,所以这个答案可能是内存的替代解决方案,即使DirectBuffer是一个类。