| File: InternalUtilities\SetWithInsertionOrder.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; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.PooledObjects; namespace Roslyn.Utilities { /// <summary> /// A set that returns the inserted values in insertion order. /// The mutation operations are not thread-safe. /// </summary> internal sealed class SetWithInsertionOrder<T> : IOrderedReadOnlySet<T> { private HashSet<T>? _set = null; private ArrayBuilder<T>? _elements = null; public bool Add(T value) { if (_set == null) { _set = new HashSet<T>(); _elements = new ArrayBuilder<T>(); } if (!_set.Add(value)) { return false; } _elements!.Add(value); return true; } public bool Insert(int index, T value) { if (_set == null) { if (index > 0) { throw new IndexOutOfRangeException(); } Add(value); } else { if (!_set.Add(value)) { return false; } try { _elements!.Insert(index, value); } catch { _set.Remove(value); throw; } } return true; } public bool Remove(T value) { if (_set is null) { return false; } if (!_set.Remove(value)) { return false; } _elements!.RemoveAt(_elements.IndexOf(value)); return true; } public int Count => _elements?.Count ?? 0; public bool Contains(T value) => _set?.Contains(value) ?? false; public IEnumerator<T> GetEnumerator() => _elements is null ? SpecializedCollections.EmptyEnumerator<T>() : ((IEnumerable<T>)_elements).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public ImmutableArray<T> AsImmutable() => _elements.ToImmutableArrayOrEmpty(); public T this[int i] => _elements![i]; private IReadOnlySet<T> Set => (IReadOnlySet<T>?)_set ?? SpecializedCollections.EmptyReadOnlySet<T>(); public bool IsProperSubsetOf(IEnumerable<T> other) => Set.IsProperSubsetOf(other); public bool IsProperSupersetOf(IEnumerable<T> other) => Set.IsProperSupersetOf(other); public bool IsSubsetOf(IEnumerable<T> other) => Set.IsSubsetOf(other); public bool IsSupersetOf(IEnumerable<T> other) => Set.IsSupersetOf(other); public bool Overlaps(IEnumerable<T> other) => Set.Overlaps(other); public bool SetEquals(IEnumerable<T> other) => Set.SetEquals(other); } }