如何在.NET中创建值类型集合

本文关键字:类型 集合 创建 NET | 更新日期: 2023-09-27 18:21:35

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

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

我已经根据经验观察到,研究已经证实,数组包装器本身在每个实例中都会引入不必要的(在这种情况下,我认为)开销。

如何使集合成为.NET中的值类型/结构?

旁注:有趣的是,苹果的Swift语言默认将数组作为值类型。

预移情评论

我完全知道以上是使用.NET框架的一种非标准方式,也是非常糟糕的做法等等…所以没有必要对此发表评论。我真的只是想知道如何实现我的要求。

如何在.NET中创建值类型集合

文档中引用的fixed关键字似乎就是您想要的。它对类型的约束与结构的约束相同,但它确实需要unsafe

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

如果您还想在结构中有一个固定的数组,那就更复杂了。fixed只支持基值类型,因此您必须手动分配内存。

DirectBuffer和BufferPool的想法可以混合使用。

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

DirectBuffer使用轻量级模式,并且添加的开销非常小。您可以直接使用指针来读取/写入任何blitable结构。据我所知,除了SBE,Flatbuffers和Cup'n Proto也使用这种方法。在链接的实现中,您应该更改委托,以便它向池返回一个丢弃的byte[]

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

更新:

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