File: Infrastructure\CopyOnWriteList.cs
Web Access
Project: src\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core)
// 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;
using System.Diagnostics;
using System.Linq;
 
namespace Microsoft.AspNetCore.Mvc.Infrastructure;
 
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(CopyOnWriteList<>.CopyOnWriteListDebugView))]
internal sealed class CopyOnWriteList<T> : IList<T>
{
    private readonly IReadOnlyList<T> _source;
    private List<T>? _copy;
 
    public CopyOnWriteList(IReadOnlyList<T> source)
    {
        _source = source;
    }
 
    private IReadOnlyList<T> Readable => _copy ?? _source;
 
    private List<T> Writable
    {
        get
        {
            if (_copy == null)
            {
                _copy = new List<T>(_source);
            }
 
            return _copy;
        }
    }
 
    public T this[int index]
    {
        get => Readable[index];
        set => Writable[index] = value;
    }
 
    public int Count => Readable.Count;
 
    public bool IsReadOnly => false;
 
    public void Add(T item)
    {
        Writable.Add(item);
    }
 
    public void Clear()
    {
        Writable.Clear();
    }
 
    public bool Contains(T item)
    {
        foreach (var obj in Readable)
        {
            if (object.Equals(obj, item))
            {
                return true;
            }
        }
 
        return false;
    }
 
    public void CopyTo(T[] array, int arrayIndex)
    {
        foreach (var item in Readable)
        {
            array[arrayIndex++] = item;
        }
    }
 
    public IEnumerator<T> GetEnumerator()
    {
        return Readable.GetEnumerator();
    }
 
    public int IndexOf(T item)
    {
        var i = 0;
        foreach (var obj in Readable)
        {
            if (object.Equals(obj, item))
            {
                return i;
            }
 
            i++;
        }
 
        return -1;
    }
 
    public void Insert(int index, T item)
    {
        Writable.Insert(index, item);
    }
 
    public bool Remove(T item)
    {
        return Writable.Remove(item);
    }
 
    public void RemoveAt(int index)
    {
        Writable.RemoveAt(index);
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
 
    private sealed class CopyOnWriteListDebugView(CopyOnWriteList<T> collection)
    {
        private readonly CopyOnWriteList<T> _collection = collection;
 
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public T[] Items => _collection.ToArray();
    }
}