Last active
September 17, 2021 14:23
-
-
Save weitzhandler/ee19db3b6dc21580d9296f86bfbb1e06 to your computer and use it in GitHub Desktop.
MultiValueDictionary<TKey, TValue>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace System.Collections.ObjectModel | |
{ | |
using System.Collections.Generic; | |
using System.Linq; | |
public class MultiValueDictionary<TKey, TElement> | |
: Collection<TElement>, ILookup<TKey, TElement> | |
{ | |
public MultiValueDictionary(Func<TElement, TKey> keyExtractor) | |
: base(new Collection(keyExtractor)) | |
{ | |
} | |
new Collection Items => (Collection)base.Items; | |
public IEnumerable<TElement> this[TKey key] => Items[key]; | |
public bool Contains(TKey key) => Items.Contains(key); | |
IEnumerator<IGrouping<TKey, TElement>> | |
IEnumerable<IGrouping<TKey, TElement>>.GetEnumerator() => Items.GetEnumerator(); | |
class Collection | |
: KeyedCollection<TKey, Grouping>, IList<TElement> | |
{ | |
Func<TElement, TKey> KeyExtractor { get; } | |
public Collection(Func<TElement, TKey> keyExtractor) => KeyExtractor = keyExtractor; | |
protected override TKey GetKeyForItem(Grouping item) => item.Key; | |
public void Add(TElement item) | |
{ | |
var key = KeyExtractor(item); | |
if (Dictionary != null && Dictionary.TryGetValue(key, out var collection)) | |
collection.Add(item); | |
else | |
Add(new Grouping(key) { item }); | |
} | |
public bool Remove(TElement item) | |
{ | |
var key = KeyExtractor(item); | |
if (Dictionary != null && Dictionary.TryGetValue(key, out var collection) | |
&& collection.Remove(item)) | |
{ | |
if (collection.Count == 0) | |
Remove(key); | |
return true; | |
} | |
return false; | |
} | |
IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator() | |
{ | |
foreach (var group in base.Items) | |
foreach (var item in group) | |
yield return item; | |
} | |
Exception IndexError() => new NotSupportedException("Indexing not supported."); | |
public int IndexOf(TElement item) => throw IndexError(); | |
public void Insert(int index, TElement item) => Add(item); | |
public bool Contains(TElement item) => Items.Contains(item); | |
public void CopyTo(TElement[] array, int arrayIndex) => throw IndexError(); | |
new IEnumerable<TElement> Items => this; | |
public bool IsReadOnly => false; | |
TElement IList<TElement>.this[int index] | |
{ | |
get => throw IndexError(); | |
set => throw IndexError(); | |
} | |
} | |
class Grouping : Collection<TElement>, IGrouping<TKey, TElement> | |
{ | |
public Grouping(TKey key) => Key = key; | |
public TKey Key { get; } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment