| File: System\Collections\Immutable\KeysOrValuesCollectionAccessor.cs | Web Access |
| Project: src\runtime\src\libraries\System.Collections.Immutable\src\System.Collections.Immutable.csproj (System.Collections.Immutable) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; namespace System.Collections.Immutable { /// <summary> /// A thin wrapper around the <see cref="IDictionary{TKey, TValue}.Keys"/> or <see cref="IDictionary{TKey, TValue}.Values"/> enumerators so they look like a collection. /// </summary> /// <typeparam name="TKey">The type of key in the dictionary.</typeparam> /// <typeparam name="TValue">The type of value in the dictionary.</typeparam> /// <typeparam name="T">Either TKey or TValue.</typeparam> internal abstract class KeysOrValuesCollectionAccessor<TKey, TValue, T> : ICollection<T>, ICollection where TKey : notnull { /// <summary> /// The underlying wrapped dictionary. /// </summary> private readonly IImmutableDictionary<TKey, TValue> _dictionary; /// <summary> /// The key or value enumerable that this instance wraps. /// </summary> private readonly IEnumerable<T> _keysOrValues; /// <summary> /// Initializes a new instance of the <see cref="KeysOrValuesCollectionAccessor{TKey, TValue, T}"/> class. /// </summary> /// <param name="dictionary">The dictionary to base on.</param> /// <param name="keysOrValues">The keys or values enumeration to wrap as a collection.</param> protected KeysOrValuesCollectionAccessor(IImmutableDictionary<TKey, TValue> dictionary, IEnumerable<T> keysOrValues) { Requires.NotNull(dictionary, nameof(dictionary)); Requires.NotNull(keysOrValues, nameof(keysOrValues)); _dictionary = dictionary; _keysOrValues = keysOrValues; } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public bool IsReadOnly { get { return true; } } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> /// <returns>The number of elements contained in the <see cref="ICollection{T}"/>.</returns> public int Count { get { return _dictionary.Count; } } /// <summary> /// Gets the wrapped dictionary. /// </summary> protected IImmutableDictionary<TKey, TValue> Dictionary { get { return _dictionary; } } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public void Add(T item) { throw new NotSupportedException(); } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public void Clear() { throw new NotSupportedException(); } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public abstract bool Contains(T item); /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public void CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, nameof(array)); Requires.Range(arrayIndex >= 0, nameof(arrayIndex)); Requires.Range(array.Length >= arrayIndex + this.Count, nameof(arrayIndex)); foreach (T item in this) { array[arrayIndex++] = item; } } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public bool Remove(T item) { throw new NotSupportedException(); } /// <summary> /// See <see cref="IEnumerable{T}"/> /// </summary> public IEnumerator<T> GetEnumerator() { return _keysOrValues.GetEnumerator(); } /// <summary> /// See <see cref="System.Collections.IEnumerable"/> /// </summary> IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } /// <summary> /// Copies the elements of the <see cref="ICollection"/> to an <see cref="Array"/>, starting at a particular <see cref="Array"/> index. /// </summary> /// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ICollection"/>. The <see cref="Array"/> must have zero-based indexing.</param> /// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param> void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, nameof(array)); Requires.Range(arrayIndex >= 0, nameof(arrayIndex)); Requires.Range(array.Length >= arrayIndex + this.Count, nameof(arrayIndex)); foreach (T item in this) { array.SetValue(item, arrayIndex++); } } /// <summary> /// Gets a value indicating whether access to the <see cref="ICollection"/> is synchronized (thread safe). /// </summary> /// <returns>true if access to the <see cref="ICollection"/> is synchronized (thread safe); otherwise, false.</returns> [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized { get { return true; } } /// <summary> /// Gets an object that can be used to synchronize access to the <see cref="ICollection"/>. /// </summary> /// <returns>An object that can be used to synchronize access to the <see cref="ICollection"/>.</returns> [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { return this; } } } /// <summary> /// A lightweight collection view over and IEnumerable of keys. /// </summary> internal sealed class KeysCollectionAccessor<TKey, TValue> : KeysOrValuesCollectionAccessor<TKey, TValue, TKey> where TKey : notnull { /// <summary> /// Initializes a new instance of the <see cref="KeysCollectionAccessor{TKey, TValue}"/> class. /// </summary> internal KeysCollectionAccessor(IImmutableDictionary<TKey, TValue> dictionary) : base(dictionary, dictionary.Keys) { } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public override bool Contains(TKey item) { return this.Dictionary.ContainsKey(item); } } /// <summary> /// A lightweight collection view over and IEnumerable of values. /// </summary> internal sealed class ValuesCollectionAccessor<TKey, TValue> : KeysOrValuesCollectionAccessor<TKey, TValue, TValue> where TKey : notnull { /// <summary> /// Initializes a new instance of the <see cref="ValuesCollectionAccessor{TKey, TValue}"/> class. /// </summary> internal ValuesCollectionAccessor(IImmutableDictionary<TKey, TValue> dictionary) : base(dictionary, dictionary.Values) { } /// <summary> /// See <see cref="ICollection{T}"/> /// </summary> public override bool Contains(TValue item) { if (this.Dictionary is ImmutableSortedDictionary<TKey, TValue> sortedDictionary) { return sortedDictionary.ContainsValue(item); } if (this.Dictionary is IImmutableDictionaryInternal<TKey, TValue> dictionary) { return dictionary.ContainsValue(item); } throw new NotSupportedException(); } } }