File: Language\Syntax\SpecializedCollections.cs
Web Access
Project: src\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable disable
 
using System;
using System.Collections;
using System.Collections.Generic;
 
namespace Microsoft.AspNetCore.Razor.Language.Syntax;
 
internal static class SpecializedCollections
{
    public static IEnumerator<T> EmptyEnumerator<T>()
    {
        return Empty.Enumerator<T>.Instance;
    }
 
    public static IEnumerable<T> EmptyEnumerable<T>()
    {
        return Empty.List<T>.Instance;
    }
 
    public static ICollection<T> EmptyCollection<T>()
    {
        return Empty.List<T>.Instance;
    }
 
    public static IList<T> EmptyList<T>()
    {
        return Empty.List<T>.Instance;
    }
 
    public static IReadOnlyList<T> EmptyReadOnlyList<T>()
    {
        return Empty.List<T>.Instance;
    }
 
    private class Empty
    {
        internal class Enumerator<T> : Enumerator, IEnumerator<T>
        {
            public static new readonly IEnumerator<T> Instance = new Enumerator<T>();
 
            protected Enumerator()
            {
            }
 
            public new T Current => throw new InvalidOperationException();
 
            public void Dispose()
            {
            }
        }
 
        internal class Enumerator : IEnumerator
        {
            public static readonly IEnumerator Instance = new Enumerator();
 
            protected Enumerator()
            {
            }
 
            public object Current => throw new InvalidOperationException();
 
            public bool MoveNext()
            {
                return false;
            }
 
            public void Reset()
            {
                throw new InvalidOperationException();
            }
        }
 
        internal class Enumerable<T> : IEnumerable<T>
        {
            // PERF: cache the instance of enumerator.
            // accessing a generic static field is kinda slow from here,
            // but since empty enumerables are singletons, there is no harm in having
            // one extra instance field
            private readonly IEnumerator<T> _enumerator = Enumerator<T>.Instance;
 
            public IEnumerator<T> GetEnumerator()
            {
                return _enumerator;
            }
 
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
 
        internal class Collection<T> : Enumerable<T>, ICollection<T>
        {
            public static readonly ICollection<T> Instance = new Collection<T>();
 
            protected Collection()
            {
            }
 
            public void Add(T item)
            {
                throw new NotSupportedException();
            }
 
            public void Clear()
            {
                throw new NotSupportedException();
            }
 
            public bool Contains(T item)
            {
                return false;
            }
 
            public void CopyTo(T[] array, int arrayIndex)
            {
            }
 
            public int Count => 0;
 
            public bool IsReadOnly => true;
 
            public bool Remove(T item)
            {
                throw new NotSupportedException();
            }
        }
 
        internal class List<T> : Collection<T>, IList<T>, IReadOnlyList<T>
        {
            public static new readonly List<T> Instance = new List<T>();
 
            protected List()
            {
            }
 
            public int IndexOf(T item)
            {
                return -1;
            }
 
            public void Insert(int index, T item)
            {
                throw new NotSupportedException();
            }
 
            public void RemoveAt(int index)
            {
                throw new NotSupportedException();
            }
 
            public T this[int index]
            {
                get
                {
                    throw new ArgumentOutOfRangeException(nameof(index));
                }
 
                set
                {
                    throw new NotSupportedException();
                }
            }
        }
    }
}