| File: InternalUtilities\OrderedMultiDictionary.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections; using System.Collections.Generic; namespace Roslyn.Utilities { // Note that this is not threadsafe for concurrent reading and writing. internal sealed class OrderedMultiDictionary<K, V> : IEnumerable<KeyValuePair<K, SetWithInsertionOrder<V>>> where K : notnull { private readonly Dictionary<K, SetWithInsertionOrder<V>> _dictionary; private readonly List<K> _keys; public int Count => _dictionary.Count; public IEnumerable<K> Keys => _keys; // Returns an empty set if there is no such key in the dictionary. public SetWithInsertionOrder<V> this[K k] { get { SetWithInsertionOrder<V>? set; return _dictionary.TryGetValue(k, out set) ? set : new SetWithInsertionOrder<V>(); } } public OrderedMultiDictionary() { _dictionary = new Dictionary<K, SetWithInsertionOrder<V>>(); _keys = new List<K>(); } public void Add(K k, V v) { SetWithInsertionOrder<V>? set; if (!_dictionary.TryGetValue(k, out set)) { _keys.Add(k); set = new SetWithInsertionOrder<V>(); } set.Add(v); _dictionary[k] = set; } public void AddRange(K k, IEnumerable<V> values) { foreach (var v in values) { Add(k, v); } } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerator<KeyValuePair<K, SetWithInsertionOrder<V>>> GetEnumerator() { foreach (var key in _keys) { yield return new KeyValuePair<K, SetWithInsertionOrder<V>>( key, _dictionary[key]); } } } }