查看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中是否有其他数据结构允许这样做,还是我必须实现自己的动态数组?
编辑:我不想要任何形式的装箱或引入任何形式的引用语义。此代码旨在实现非常高的性能,以及我使用结构数组的原因是让它们在内存中紧密包装(而不是堆在堆中,导致缓存未命中)。
我想修改结构,因为它是性能关键算法的一部分,它将一些数据存储在这些结构中。
答案 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>
类,则可以通过直接索引获得Add
,Insert
,Sort
的方法的可重用性和方便性以及直接元素访问在阵列上。只需运用一些约束,永远不要将句柄存储到内部数组,因为下次列表需要增加容量时,它将变得过时。立即直接访问完全没问题。