问题 枚举Dictionary.Values vs Dictionary本身


我正在GitHub上探索ASP.NET核心的来源,看看ASP.NET团队用来加速框架的那种技巧。我看到一些引起我兴趣的东西。在源代码中 服务提供者,在Dispose实现中,他们枚举一个字典,他们发表评论来表明一个表演技巧:

private readonly Dictionary<IService, object> _resolvedServices = new Dictionary<IService, object>();

// Code removed for brevity

public void Dispose()    
{        
    // Code removed for brevity

    // PERF: We've enumerating the dictionary so that we don't allocate to enumerate.
    // .Values allocates a KeyCollection on the heap, enumerating the dictionary allocates
    // a struct enumerator
    foreach (var entry in _resolvedServices)
    {
        (entry.Value as IDisposable)?.Dispose();
    }

    _resolvedServices.Clear();        
}

如果字典是这样列举的,有什么区别?

foreach (var entry in _resolvedServices.Values)
{
    (entry as IDisposable)?.Dispose();
}

它有性能影响吗?或者是因为分配了一个 ValueCollection 会消耗更多的内存吗?


7210
2018-04-16 00:53


起源



答案:


你是对的,这是关于内存消耗的。差异实际上在评论中有很好的描述:访问 Value 的财产 Dictionary<TKey, TValue>  将分配一个 ValueCollection,这是一个类(引用类型),在堆上。

foreach通过字典本身会导致调用 GetEnumerator() 返回一个 Enumerator。这是一个 struct 并将分配在堆栈而不是堆上。


9
2018-04-16 06:46



我似乎错过了这里很好描述的堆积和堆叠的概念 c-sharpcorner.com/UploadFile/rmcochran/... 谢谢你的方式。 - Fabien PERRONNET


答案:


你是对的,这是关于内存消耗的。差异实际上在评论中有很好的描述:访问 Value 的财产 Dictionary<TKey, TValue>  将分配一个 ValueCollection,这是一个类(引用类型),在堆上。

foreach通过字典本身会导致调用 GetEnumerator() 返回一个 Enumerator。这是一个 struct 并将分配在堆栈而不是堆上。


9
2018-04-16 06:46



我似乎错过了这里很好描述的堆积和堆叠的概念 c-sharpcorner.com/UploadFile/rmcochran/... 谢谢你的方式。 - Fabien PERRONNET