File: System\Text\Json\Nodes\JsonArray.IList.cs
Web Access
Project: src\src\libraries\System.Text.Json\src\System.Text.Json.csproj (System.Text.Json)
// 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.Collections.Generic;
 
namespace System.Text.Json.Nodes
{
    public sealed partial class JsonArray : JsonNode, IList<JsonNode?>
    {
        /// <summary>
        ///   Gets the number of elements contained in the <see cref="JsonArray"/>.
        /// </summary>
        public int Count => List.Count;
 
        /// <summary>
        ///   Adds a <see cref="JsonNode"/> to the end of the <see cref="JsonArray"/>.
        /// </summary>
        /// <param name="item">
        ///   The <see cref="JsonNode"/> to be added to the end of the <see cref="JsonArray"/>.
        /// </param>
        public void Add(JsonNode? item)
        {
            item?.AssignParent(this);
 
            List.Add(item);
        }
 
        /// <summary>
        ///   Removes all elements from the <see cref="JsonArray"/>.
        /// </summary>
        public void Clear()
        {
            List<JsonNode?>? list = _list;
 
            if (list is null)
            {
                _jsonElement = null;
            }
            else
            {
                for (int i = 0; i < list.Count; i++)
                {
                    DetachParent(list[i]);
                }
 
                list.Clear();
            }
        }
 
        /// <summary>
        ///   Determines whether an element is in the <see cref="JsonArray"/>.
        /// </summary>
        /// <param name="item">The object to locate in the <see cref="JsonArray"/>.</param>
        /// <returns>
        ///   <see langword="true"/> if <paramref name="item"/> is found in the <see cref="JsonArray"/>; otherwise, <see langword="false"/>.
        /// </returns>
        public bool Contains(JsonNode? item) => List.Contains(item);
 
        /// <summary>
        ///   The object to locate in the <see cref="JsonArray"/>.
        /// </summary>
        /// <param name="item">The <see cref="JsonNode"/> to locate in the <see cref="JsonArray"/>.</param>
        /// <returns>
        ///  The index of item if found in the list; otherwise, -1.
        /// </returns>
        public int IndexOf(JsonNode? item) => List.IndexOf(item);
 
        /// <summary>
        ///   Inserts an element into the <see cref="JsonArray"/> at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
        /// <param name="item">The <see cref="JsonNode"/> to insert.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="index"/> is less than 0 or <paramref name="index"/> is greater than <see cref="Count"/>.
        /// </exception>
        public void Insert(int index, JsonNode? item)
        {
            item?.AssignParent(this);
            List.Insert(index, item);
        }
 
        /// <summary>
        ///   Removes the first occurrence of a specific <see cref="JsonNode"/> from the <see cref="JsonArray"/>.
        /// </summary>
        /// <param name="item">
        ///   The <see cref="JsonNode"/> to remove from the <see cref="JsonArray"/>.
        /// </param>
        /// <returns>
        ///   <see langword="true"/> if <paramref name="item"/> is successfully removed; otherwise, <see langword="false"/>.
        /// </returns>
        public bool Remove(JsonNode? item)
        {
            if (List.Remove(item))
            {
                DetachParent(item);
                return true;
            }
 
            return false;
        }
 
        /// <summary>
        ///   Removes the element at the specified index of the <see cref="JsonArray"/>.
        /// </summary>
        /// <param name="index">The zero-based index of the element to remove.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="index"/> is less than 0 or <paramref name="index"/> is greater than <see cref="Count"/>.
        /// </exception>
        public void RemoveAt(int index)
        {
            JsonNode? item = List[index];
            List.RemoveAt(index);
            DetachParent(item);
        }
 
        /// <summary>
        ///   Removes all the elements that match the conditions defined by the specified predicate.
        /// </summary>
        /// <param name="match">The predicate that defines the conditions of the elements to remove.</param>
        /// <returns>The number of elements removed from the <see cref="JsonArray"/>.</returns>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="match"/> is <see langword="null"/>.
        /// </exception>
        public int RemoveAll(Func<JsonNode?, bool> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(match));
            }
 
            return List.RemoveAll(node =>
            {
                if (match(node))
                {
                    DetachParent(node);
                    return true;
                }
                else
                {
                    return false;
                }
            });
        }
 
        /// <summary>
        ///   Removes a range of elements from the <see cref="JsonArray"/>.
        /// </summary>
        /// <param name="index">The zero-based starting index of the range of elements to remove.</param>
        /// <param name="count">The number of elements to remove.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="index"/> or <paramref name="count"/> is less than 0.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="index"/> and <paramref name="count"/> do not denote a valid range of elements in the <see cref="JsonArray"/>.
        /// </exception>
        public void RemoveRange(int index, int count)
        {
            if (index < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException_NeedNonNegNum(nameof(index));
            }
 
            if (count < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException_NeedNonNegNum(nameof(count));
            }
 
            List<JsonNode?> list = List;
 
            if (list.Count - index < count)
            {
                ThrowHelper.ThrowArgumentException_InvalidOffLen();
            }
 
            if (count > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    DetachParent(list[index + i]);
                    // There's no need to assign nulls because List<>.RemoveRange calls
                    // Array.Clear on the removed partition.
                }
 
                list.RemoveRange(index, count);
            }
        }
 
        #region Explicit interface implementation
 
        /// <summary>
        ///   Copies the entire <see cref="Array"/> to a compatible one-dimensional array,
        ///   starting at the specified index of the target array.
        /// </summary>
        /// <param name="array">
        ///   The one-dimensional <see cref="Array"/> that is the destination of the elements copied
        ///   from <see cref="JsonArray"/>. The Array must have zero-based indexing.</param>
        /// <param name="index">
        ///   The zero-based index in <paramref name="array"/> at which copying begins.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="array"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="index"/> is less than 0.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   The number of elements in the source ICollection is greater than the available space from <paramref name="index"/>
        ///   to the end of the destination <paramref name="array"/>.
        /// </exception>
        void ICollection<JsonNode?>.CopyTo(JsonNode?[] array, int index) => List.CopyTo(array, index);
 
        /// <summary>
        ///   Returns an enumerator that iterates through the <see cref="JsonArray"/>.
        /// </summary>
        /// <returns>A <see cref="IEnumerator{JsonNode}"/> for the <see cref="JsonNode"/>.</returns>
        public IEnumerator<JsonNode?> GetEnumerator() => List.GetEnumerator();
 
        /// <summary>
        ///   Returns an enumerator that iterates through the <see cref="JsonArray"/>.
        /// </summary>
        /// <returns>
        ///   A <see cref="IEnumerator"/> for the <see cref="JsonArray"/>.
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)List).GetEnumerator();
 
        /// <summary>
        ///   Returns <see langword="false"/>.
        /// </summary>
        bool ICollection<JsonNode?>.IsReadOnly => false;
 
        #endregion
 
        private static void DetachParent(JsonNode? item)
        {
            if (item != null)
            {
                item.Parent = null;
            }
        }
    }
}