FrozenDictionary<TKey, TValue>
public abstract class FrozenDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection
Provides an immutable, read-only dictionary optimized for fast lookup and enumeration.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Collections.Frozen
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
[DebuggerTypeProxy(typeof(ImmutableDictionaryDebuggerProxy<, >))]
[DebuggerDisplay("Count = {Count}")]
public abstract class FrozenDictionary<TKey, [System.Runtime.CompilerServices.Nullable(2)] TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection
{
[System.Runtime.CompilerServices.NullableContext(0)]
public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IEnumerator, IDisposable
{
private readonly TKey[] _keys;
private readonly TValue[] _values;
private int _index;
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1,
1
})]
public KeyValuePair<TKey, TValue> Current {
[System.Runtime.CompilerServices.IsReadOnly]
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1,
1
})]
get {
if ((uint)_index >= (uint)_keys.Length)
ThrowHelper.ThrowInvalidOperationException();
return new KeyValuePair<TKey, TValue>(_keys[_index], _values[_index]);
}
}
[System.Runtime.CompilerServices.Nullable(1)]
object IEnumerator.Current {
get {
return Current;
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
internal Enumerator(TKey[] keys, TValue[] values)
{
_keys = keys;
_values = values;
_index = -1;
}
public bool MoveNext()
{
_index++;
if ((uint)_index < (uint)_keys.Length)
return true;
_index = _keys.Length;
return false;
}
void IEnumerator.Reset()
{
_index = -1;
}
void IDisposable.Dispose()
{
}
}
public static FrozenDictionary<TKey, TValue> Empty { get; } = new EmptyFrozenDictionary<TKey, TValue>(EqualityComparer<TKey>.Default);
public IEqualityComparer<TKey> Comparer { get; }
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public ImmutableArray<TKey> Keys {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
get {
return ImmutableCollectionsMarshal.AsImmutableArray<TKey>(KeysCore);
}
}
private protected abstract TKey[] KeysCore { get; }
ICollection<TKey> IDictionary<TKey, TValue>.Keys {
get {
ImmutableArray<TKey> keys = Keys;
if (keys.Length <= 0)
return Array.Empty<TKey>();
return keys;
}
}
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys {
get {
return ((IDictionary<TKey, TValue>)this).Keys;
}
}
ICollection IDictionary.Keys {
get {
return Keys;
}
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public ImmutableArray<TValue> Values {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
get {
return ImmutableCollectionsMarshal.AsImmutableArray<TValue>(ValuesCore);
}
}
private protected abstract TValue[] ValuesCore { get; }
ICollection<TValue> IDictionary<TKey, TValue>.Values {
get {
ImmutableArray<TValue> values = Values;
if (values.Length <= 0)
return Array.Empty<TValue>();
return values;
}
}
ICollection IDictionary.Values {
get {
return Values;
}
}
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values {
get {
return ((IDictionary<TKey, TValue>)this).Values;
}
}
public int Count => CountCore;
private protected abstract int CountCore { get; }
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
get {
return true;
}
}
bool IDictionary.IsReadOnly {
get {
return true;
}
}
bool IDictionary.IsFixedSize {
get {
return true;
}
}
bool ICollection.IsSynchronized {
get {
return false;
}
}
object ICollection.SyncRoot {
get {
return this;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
object IDictionary.this[object key] {
get {
ThrowHelper.ThrowIfNull(key, "key");
if (key is TKey) {
TKey key2 = (TKey)key;
if (TryGetValue(key2, out TValue value))
return value;
}
return null;
}
set {
throw new NotSupportedException();
}
}
[System.Runtime.CompilerServices.IsReadOnly]
public ref TValue this[TKey key] {
[return: System.Runtime.CompilerServices.IsReadOnly]
get {
ref TValue valueRefOrNullRef = ref GetValueRefOrNullRef(key);
if (Unsafe.IsNullRef<TValue>(ref Unsafe.AsRef<TValue>(ref valueRefOrNullRef)))
ThrowHelper.ThrowKeyNotFoundException<TKey>(key);
return ref valueRefOrNullRef;
}
}
TValue IDictionary<TKey, TValue>.this[TKey key] {
get {
return this[key];
}
set {
throw new NotSupportedException();
}
}
TValue IReadOnlyDictionary<TKey, TValue>.this[TKey key] {
get {
return this[key];
}
}
private protected FrozenDictionary(IEqualityComparer<TKey> comparer)
{
Comparer = comparer;
}
public void CopyTo([System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0,
1,
1
})] KeyValuePair<TKey, TValue>[] destination, int destinationIndex)
{
ThrowHelper.ThrowIfNull(destination, "destination");
CopyTo(MemoryExtensions.AsSpan<KeyValuePair<TKey, TValue>>(destination, destinationIndex));
}
public void CopyTo([System.Runtime.CompilerServices.Nullable(new byte[] {
0,
0,
1,
1
})] Span<KeyValuePair<TKey, TValue>> destination)
{
if (destination.Length < Count)
ThrowHelper.ThrowIfDestinationTooSmall();
TKey[] keysCore = KeysCore;
TValue[] valuesCore = ValuesCore;
for (int i = 0; i < keysCore.Length; i++) {
destination[i] = new KeyValuePair<TKey, TValue>(keysCore[i], valuesCore[i]);
}
}
void ICollection.CopyTo(Array array, int index)
{
ThrowHelper.ThrowIfNull(array, "array");
if (array.Rank != 1)
throw new ArgumentException(System.SR.Arg_RankMultiDimNotSupported, "array");
if (array.GetLowerBound(0) != 0)
throw new ArgumentException(System.SR.Arg_NonZeroLowerBound, "array");
if ((uint)index > (uint)array.Length)
throw new ArgumentOutOfRangeException("index", System.SR.ArgumentOutOfRange_NeedNonNegNum);
if (array.Length - index < Count)
throw new ArgumentException(System.SR.Arg_ArrayPlusOffTooSmall, "array");
KeyValuePair<TKey, TValue>[] array2 = array as KeyValuePair<TKey, TValue>[];
Enumerator enumerator;
if (array2 != null) {
enumerator = GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<TKey, TValue> current = enumerator.Current;
array2[index++] = new KeyValuePair<TKey, TValue>(current.Key, current.Value);
}
} finally {
((IDisposable)enumerator).Dispose();
}
} else {
DictionaryEntry[] array3 = array as DictionaryEntry[];
if (array3 != null) {
enumerator = GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<TKey, TValue> current2 = enumerator.Current;
array3[index++] = new DictionaryEntry(current2.Key, current2.Value);
}
} finally {
((IDisposable)enumerator).Dispose();
}
} else {
object[] array4 = array as object[];
if (array4 == null)
throw new ArgumentException(System.SR.Argument_IncompatibleArrayType, "array");
try {
enumerator = GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<TKey, TValue> current3 = enumerator.Current;
array4[index++] = new KeyValuePair<TKey, TValue>(current3.Key, current3.Value);
}
} finally {
((IDisposable)enumerator).Dispose();
}
} catch (ArrayTypeMismatchException) {
throw new ArgumentException(System.SR.Argument_IncompatibleArrayType, "array");
}
}
}
}
[return: System.Runtime.CompilerServices.IsReadOnly]
public ref TValue GetValueRefOrNullRef(TKey key)
{
if (key == null)
ThrowHelper.ThrowArgumentNullException("key");
return ref GetValueRefOrNullRefCore(key);
}
[return: System.Runtime.CompilerServices.IsReadOnly]
private protected abstract ref TValue GetValueRefOrNullRefCore(TKey key);
[return: System.Runtime.CompilerServices.IsReadOnly]
private protected virtual ref TValue GetValueRefOrNullRefCore<TAlternateKey>(TAlternateKey key)
{
return ref Unsafe.NullRef<TValue>();
}
public bool ContainsKey(TKey key)
{
return !Unsafe.IsNullRef<TValue>(ref Unsafe.AsRef<TValue>(ref GetValueRefOrNullRef(key)));
}
bool IDictionary.Contains(object key)
{
ThrowHelper.ThrowIfNull(key, "key");
if (key is TKey) {
TKey key2 = (TKey)key;
return ContainsKey(key2);
}
return false;
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
if (TryGetValue(item.Key, out TValue value))
return EqualityComparer<TValue>.Default.Equals(value, item.Value);
return false;
}
public bool TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TValue value)
{
ref TValue valueRefOrNullRef = ref GetValueRefOrNullRef(key);
if (!Unsafe.IsNullRef<TValue>(ref Unsafe.AsRef<TValue>(ref valueRefOrNullRef))) {
value = valueRefOrNullRef;
return true;
}
value = default(TValue);
return false;
}
[System.Runtime.CompilerServices.NullableContext(0)]
public Enumerator GetEnumerator()
{
return GetEnumeratorCore();
}
[System.Runtime.CompilerServices.NullableContext(0)]
private protected abstract Enumerator GetEnumeratorCore();
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
if (Count != 0)
return GetEnumerator();
return ((IEnumerable<KeyValuePair<TKey, TValue>>)Array.Empty<KeyValuePair<TKey, TValue>>()).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
if (Count != 0)
return GetEnumerator();
return Array.Empty<KeyValuePair<TKey, TValue>>().GetEnumerator();
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return new DictionaryEnumerator<TKey, TValue>(GetEnumerator());
}
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
throw new NotSupportedException();
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException();
}
void IDictionary.Add(object key, object value)
{
throw new NotSupportedException();
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
throw new NotSupportedException();
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException();
}
void IDictionary.Remove(object key)
{
throw new NotSupportedException();
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw new NotSupportedException();
}
void IDictionary.Clear()
{
throw new NotSupportedException();
}
}
}