是否有类似动态数组的List <t>允许访问.NET中的内部数组数据?

时间:2016-10-06 21:30:07

标签: c# arrays collections

查看List<T>的来源,似乎没有好方法可以访问私有_items项目数组。

我需要的基本上是struct s的动态列表,我可以在其中进行修改。根据我的理解,因为C#6还不支持ref返回类型,所以你不能让List<T>返回对元素的引用,这需要复制整个项目,例如:

struct A {
  public int X;
}

void Foo() {
  var list = new List<A> { new A { X = 3; } };

  list[0].X++; // this fails to compile, because the indexer returns a copy

  // a proper way to do this would be
  var copy = list[0];
  copy.X++;
  list[0] = copy;


  var array = new A[] { new A { X = 3; } };

  array[0].X++; // this works just fine    
}

从这个角度来看,它从语法的角度来看都很笨拙,并且可能比修改数据要慢得多(除非JIT可以针对这种特殊情况做一些神奇的优化?但我怀疑它们可能是在一般情况下依赖,除非它是一种特殊的标准化优化?)

现在,如果List<T>._items受到保护,则至少可以创建一个具有特定修改操作的数据结构List<T>。 .NET中是否有其他数据结构允许这样做,还是我必须实现自己的动态数组?

编辑:我不想要任何形式的装箱或引入任何形式的引用语义。此代码旨在实现非常高的性能,以及我使用结构数组的原因是让它们在内存中紧密包装(而不是堆在堆中,导致缓存未命中)。

我想修改结构,因为它是性能关键算法的一部分,它将一些数据存储在这些结构中。

1 个答案:

答案 0 :(得分:3)

  

.NET中是否有其他数据结构允许这样做,还是我必须实现自己的动态数组?

都不是。

没有,不能,这是.NET中一种避免结构副本的数据结构,因为需要与C#语言进行深度集成才能绕过&#34;索引的getter制作副本&#34;问题。因此,您可以直接考虑直接访问数组。

但是你不必从头开始构建自己的动态数组。许多List<T> - 类似Resize等操作以及项目的批量移动都是作为System.Array类型的静态方法提供的。它们有通用的味道,所以不涉及拳击。

不幸的是, 应该在任何blittable类型上工作的高性能Buffer.BlockCopy实际上包含对原始类型的硬编码检查,并拒绝在任何结构上工作

所以只需使用T[](加int Count - 数组长度不够好,因为尝试保持容量等于计数是非常低效的)并使用System.Array静态否则您将使用List<T>方法的方法。如果将其包装为PublicList<T>类,则可以通过直接索引获得AddInsertSort的方法的可重用性和方便性以及直接元素访问在阵列上。只需运用一些约束,永远不要将句柄存储到内部数组,因为下次列表需要增加容量时,它将变得过时。立即直接访问完全没问题。