获取列表数组并保留引用?

如何解决获取列表数组并保留引用?

出于某种性能原因,我想直接在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.AddList.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>.CapacityArray.LengthList<T>.Count()是三个差异值。

解决方法

更改List<T>Count(实际上是Capacity时,是因为列表的内部数组已调整大小。

调整大型数组的大小需要分配一个新数组并复制其内容,而忘记了旧的内存空间。

理论上,收缩不是问题,只需要“切割”阵列即可。

但是由于内存单元的组织,如果不使用具有可用空间的全新连续块,就无法确保增长。

Array.Resize(T[],Int32) Method

此方法分配具有指定大小的新数组,将元素从旧数组复制到新数组,然后用新数组替换旧数组。数组必须是一维数组。

因此,您无法避免:每次调整数组大小时,都需要重新获取它。

因此,除非您一次执行此类操作并确保数组的容量不会发生变化,否则我不建议您使用该技术,因为很难确保您始终拥有正确的数组而不是遗弃的引用。

因此,您应该使用现有的方法List<T>.ToArray()

但是实际上,如果可以的话,因为要提高速度,应该使用Array而不是List

正如您所看到的,当List上的CapacityCountList<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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-