Перечислить словарь. Вали против самого словаря

Я изучал источники ядра ASP.NET на GitHub, чтобы узнать, какие трюки команда ASP.NET использовала для ускорения работы платформы. Я увидел то, что меня заинтриговало. В исходном коде ServiceProvider в реализации 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 будет потреблять больше памяти?

Ответ 1

Вы правы, речь идет о потреблении памяти. Разница на самом деле довольно хорошо описана в комментарии: доступ к свойству Value объекта Dictionary<TKey, TValue> будет выделять ValueCollection, который является классом (ссылочный тип), в куче.

foreach через сам словарь приводит к вызову GetEnumerator(), который возвращает Enumerator. Это struct и будет выделено в стеке, а не в куче.