System.Array.IndexOf 分配内存

我一直在分析我的代码,发现它System.Array.IndexOf分配了相当多的内存。我一直在试图找出这是怎么发生的。

http://img4.mukewang.com/61da504000014b8b12130043.jpg

public struct LRItem

{

    public ProductionRule Rule { get; } // ProductionRule is a class

    public int Position { get; }

}


// ...


public List<LRItem> Items { get; } = new List<LRItem>();


// ...


public bool Add(LRItem item)

{

    if (Items.Contains(item)) return false;


    Items.Add(item);

    return true;

}

我假设IndexOf被调用是Items.Contains因为我认为Items.Add没有任何业务检查索引。我尝试查看参考源和.NET Core 源,但无济于事。这是 VS 分析器中的错误吗?这个函数实际上是在分配内存吗?我可以以某种方式优化我的代码吗?


犯罪嫌疑人X
浏览 173回答 2
2回答

尚方宝剑之说

我知道这可能有点晚了,但万一其他人有同样的问题......当List<T>.Contains(...)被调用时,它使用了EqualityComparer<T>.Default比较个别项目发现你在[1]通过什么。该文件说,这一下EqualityComparer<T>.Default:Default 属性检查类型 T 是否实现了 System.IEquatable 接口,如果是,则返回使用该实现的 EqualityComparer。否则,它返回一个使用 T 提供的 Object.Equals 和 Object.GetHashCode 覆盖的 EqualityComparer。由于您LRItem没有不执行IEquatable<T>的话,就回退到使用Object.Equals(object, object)。因为LRItem是一个结构,所以它最终会被装箱为一个,object所以它可以被传递给Object.Equals(...),这是分配的来源。解决此问题的简单方法是从文档中获取提示并实现IEquatable<T>接口:public&nbsp;struct&nbsp;LRItem&nbsp;:&nbsp;IEquatable<LRItem>{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;bool&nbsp;Equals(LRItem&nbsp;other) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Implement&nbsp;this &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;}}现在这将导致EqualityComparer<T>.Default返回一个不需要对LRItem结构进行装箱的专用比较器,从而避免分配。[1] 我不确定自从提出这个问题以来是否发生了一些变化(或者可能是 .net 框架与核心差异之类的东西),但现在List<T>.Contains()没有调用Array.IndexOf()。无论哪种方式,它们都遵循EqualityComparer<T>.Default,这意味着这在任何一种情况下都应该是相关的。

函数式编程

您的对象不是像 text 或 number 这样的简单数据类型,因此检查每个项目中的复杂对象可能是内存杀手。例如,如果您的对象包含图像、文本、数字和......每个数据都应该进行相似性处理。我建议您不要使用 IndexOf 或 Contains 函数,因为它们&nbsp;可能会比较对象中的每一个数据。只是做手工,用一个单一的foreach循环和只是比较你的关键数据(用户ID,对象ID,姓名,家庭,日期,时间或......)。
打开App,查看更多内容
随时随地看视频慕课网APP