c# - System.Array.IndexOf 分配内存

标签 c# .net-core profiling system.array

我一直在分析我的代码,发现System.Array.IndexOf正在分配相当多的内存。我一直在试图找出为什么会发生这种情况。

profiler image

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 没有任何业务检查索引。我尝试查看 reference source.NET Core source但无济于事。这是 VS 分析器中的错误吗?这个函数实际上是在分配内存吗?我可以以某种方式优化我的代码吗?

最佳答案

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

何时 List<T>.Contains(...)被调用,它使用 EqualityComparer<T>.Default比较各个项目以查找您传入的内容[1]。 docs说一下EqualityComparer<T>.Default :

The Default property checks whether type T implements the System.IEquatable interface and, if so, returns an EqualityComparer that uses that implementation. Otherwise, it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

自从您的 LRItem 没有实现 IEquatable<T> ,然后又使用 Object.Equals(object, object) 。因为LRItem是一个结构体,那么它最终会被装箱object所以它可以传入 Object.Equals(...) ,这是分配的来源。

解决这个问题的简单方法是从文档中获取提示并实现 IEquatable<T>接口(interface):

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 ,这意味着这在任何一种情况下都应该仍然相关。

关于c# - System.Array.IndexOf 分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52233941/

相关文章:

Android Profiling 对所选进程不可用,但已启用高级分析

CUDA - 在远程计算机上运行 NVVP,在没有启用 CUDA 的设备的本地计算机上显示结果

c# - 将整数转换为书面数字

c# - 为什么我不能在C#中设置这个ACL规则?

asp.net-core - 如何在 IServiceCollection.Configure() 中使用 IServiceProvider

c# - Blazor 处理来自 Web Api 的响应中的错误

language-agnostic - CPU 或 GPU 绑定(bind)?分析 OpenGL 应用程序

c# - 对 asp.net web api 进行 Restful 调用

c# - Watin新版本2.1访问Frames时出错

c# - 从 ASP.NET CORE 2 获取当前用户