如何解决获取列表数组并保留引用?
出于某种性能原因,我想直接在C#中获取List数组
https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,2765070d40f47b98
我的代码在这里:
private UIVertex[] GetArray(List<UIVertex> verts)
{
var aryF = typeof(List<UIVertex>).GetField("_items",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
return aryF.GetValue(verts) as UIVertex[];
}
private void SetSize(List<UIVertex> list,int size)
{
sizeF = typeof(List<UIVertex>).GetField("_size",System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
}
static List<UIVertex> verts
static UIVertex[] ary;
//...
ary = GetArray(verts);
就我而言,我可以重用'verts',但是当'verts'计数改变时。我的ary需要再次获得(它称为反射),
反射成本太高了,我能保留一下参考吗?怎么做?
PS:
当我使用List.Add
或List.Get
时,它会触发String.memcpy()
,它太慢了,这就是为什么我要直接使用数组。
并且因为我重用了List,所以array Length不会自动改变。我可以保持引用快速。
PS 2。
在此之前进行修改:
static List<T> Orgin = new List<T>(128);
void DO() // *it call a lot of times.*
{
GetListByAPI(Orgin);// here is API,So it must insert List<T>.
int Size = Orgin.Count() * 5; // size is unchanged in here.
if(Orgin.Capacity < Size)
{
Orgin.Capacity = Size;
}
for(int i = Orgin.Count() ; i < Size ;i++)
{
T t
Orgin.Add(t);// I need "Oring.Count() * 5 " Size Array for my logic.
//...
}
}
在这里修改:
static List<T> Orgin = new List<T>(128);
static T[] StaticAry;
void DO() // *it call a lot of times.*
{
bool LastOringCapacity = Orgin.Capacity;
GetListByAPI(Orgin);// here is API,So it must insert List<T>.
bool arrayRefChanged = Orgin.Capacity > LastOringCapacity ; // I Can know it. and get array again.
int Size = Orgin.Count() * 5; // size is unchanged in here.
SetSize(Oring,Size);//here set array legth of list by refection
StaticAry = GetArray(Orgin);//here I get array of list by reflection
for(int i = 0 ; i < size; i++)
{
T t = StaticAry[i];//just use it,avoid to use List.Add api.
//....
}
}
此静态Orgin正在重用,因此Oring.Capacity可能不会更改。因此,Orgin数组也不会调整大小。我想获得数组地址。直接使用它。 但现在。我需要使用反射来获取每个DO()中的数组。
最复杂的地方是
List<T>.Capacity
和Array.Length
和List<T>.Count()
是三个差异值。
解决方法
更改List<T>Count
(实际上是Capacity
时,是因为列表的内部数组已调整大小。
调整大型数组的大小需要分配一个新数组并复制其内容,而忘记了旧的内存空间。
理论上,收缩不是问题,只需要“切割”阵列即可。
但是由于内存单元的组织,如果不使用具有可用空间的全新连续块,就无法确保增长。
Array.Resize(T[],Int32) Method:
此方法分配具有指定大小的新数组,将元素从旧数组复制到新数组,然后用新数组替换旧数组。数组必须是一维数组。
因此,您无法避免:每次调整数组大小时,都需要重新获取它。
因此,除非您一次执行此类操作并确保数组的容量不会发生变化,否则我不建议您使用该技术,因为很难确保您始终拥有正确的数组而不是遗弃的引用。
因此,您应该使用现有的方法List<T>.ToArray()
。
但是实际上,如果可以的话,因为要提高速度,应该使用Array而不是List
。
正如您所看到的,当List
上的Capacity
或Count
在List<T>.Capacity中发生变化时,Capacity
会发生什么:
T[] newItems = new T[value];
if (_size > 0) {
Array.Copy(_items,newItems,_size);
}
_items = newItems;
这是Add
方法:
public void Add(T item) {
if (_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size++] = item;
_version++;
}
Array.Resize()
做同样的事情:
if (larray.Length != newSize) {
T[] newArray = new T[newSize];
Array.Copy(larray,newArray,larray.Length > newSize? newSize : larray.Length);
array = newArray;
}
我认为这可能已针对缩小尺寸进行了优化,但可能与CLR或GC有关。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。