为了账号安全,请及时绑定邮箱和手机立即绑定

System.Array.IndexOf 分配内存

System.Array.IndexOf 分配内存

C#
犯罪嫌疑人X 2022-01-09 11:02:03
我一直在分析我的代码,发现它System.Array.IndexOf分配了相当多的内存。我一直在试图找出这是怎么发生的。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 分析器中的错误吗?这个函数实际上是在分配内存吗?我可以以某种方式优化我的代码吗?
查看完整描述

2 回答

?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

我知道这可能有点晚了,但万一其他人有同样的问题......

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 struct LRItem : IEquatable<LRItem>{
    // ...
    public bool Equals(LRItem other)
    {
        // Implement this
        return true;
    }}

现在这将导致EqualityComparer<T>.Default返回一个不需要对LRItem结构进行装箱的专用比较器,从而避免分配。

[1] 我不确定自从提出这个问题以来是否发生了一些变化(或者可能是 .net 框架与核心差异之类的东西),但现在List<T>.Contains()没有调用Array.IndexOf()。无论哪种方式,它们遵循EqualityComparer<T>.Default,这意味着这在任何一种情况下都应该是相关的。


查看完整回答
反对 回复 2022-01-09
?
函数式编程

TA贡献1807条经验 获得超9个赞

您的对象不是像 text 或 number 这样的简单数据类型,因此检查每个项目中的复杂对象可能是内存杀手。

例如,如果您的对象包含图像、文本、数字和......每个数据都应该进行相似性处理。

我建议您不要使用 IndexOf 或 Contains 函数,因为它们 可能会比较对象中的每一个数据。

只是做手工,用一个单一的foreach循环和只是比较你的关键数据(用户ID,对象ID,姓名,家庭,日期,时间或......)。


查看完整回答
反对 回复 2022-01-09
  • 2 回答
  • 0 关注
  • 172 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信