File: System\Xml\Xsl\ListBase.cs
Web Access
Project: src\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
 
namespace System.Xml.Xsl
{
    /// <summary>
    /// Implementation of read-only IList and IList{T} interfaces.  Derived classes can inherit from
    /// this class and implement only two methods, Count and Item, rather than the entire IList interface.
    /// </summary>
    internal abstract class ListBase<T> : IList<T>, System.Collections.IList
    {
        //-----------------------------------------------
        // Abstract IList methods that must be
        // implemented by derived classes
        //-----------------------------------------------
        public abstract int Count { get; }
        public abstract T this[int index] { get; set; }
 
 
        //-----------------------------------------------
        // Implemented by base class -- accessible on
        // ListBase
        //-----------------------------------------------
        public virtual bool Contains(T value)
        {
            return IndexOf(value) != -1;
        }
 
        public virtual int IndexOf(T value)
        {
            for (int i = 0; i < Count; i++)
                if (value!.Equals(this[i]))
                    return i;
 
            return -1;
        }
 
        public virtual void CopyTo(T[] array, int index)
        {
            for (int i = 0; i < Count; i++)
                array[index + i] = this[i];
        }
 
        public virtual IListEnumerator<T> GetEnumerator()
        {
            return new IListEnumerator<T>(this);
        }
 
        public virtual bool IsFixedSize
        {
            get { return true; }
        }
 
        public virtual bool IsReadOnly
        {
            get { return true; }
        }
 
        public virtual void Add(T value)
        {
            Insert(Count, value);
        }
 
        public virtual void Insert(int index, T value)
        {
            throw new NotSupportedException();
        }
 
        public virtual bool Remove(T value)
        {
            int index = IndexOf(value);
            if (index >= 0)
            {
                RemoveAt(index);
                return true;
            }
            return false;
        }
 
        public virtual void RemoveAt(int index)
        {
            throw new NotSupportedException();
        }
 
        public virtual void Clear()
        {
            for (int index = Count - 1; index >= 0; index--)
                RemoveAt(index);
        }
 
 
        //-----------------------------------------------
        // Implemented by base class -- only accessible
        // after casting to IList
        //-----------------------------------------------
        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return new IListEnumerator<T>(this);
        }
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new IListEnumerator<T>(this);
        }
 
        bool System.Collections.ICollection.IsSynchronized
        {
            get { return IsReadOnly; }
        }
 
        object System.Collections.ICollection.SyncRoot
        {
            get { return this; }
        }
 
        void System.Collections.ICollection.CopyTo(Array array, int index)
        {
            for (int i = 0; i < Count; i++)
                array.SetValue(this[i], index);
        }
 
        object? System.Collections.IList.this[int index]
        {
            get { return this[index]; }
            set
            {
                if (!IsCompatibleType(value!.GetType()))
                    throw new ArgumentException(SR.Arg_IncompatibleParamType, nameof(value));
 
                this[index] = (T)value;
            }
        }
 
        int System.Collections.IList.Add(object? value)
        {
            if (!IsCompatibleType(value!.GetType()))
                throw new ArgumentException(SR.Arg_IncompatibleParamType, nameof(value));
 
            Add((T)value);
            return Count - 1;
        }
 
        void System.Collections.IList.Clear()
        {
            Clear();
        }
 
        bool System.Collections.IList.Contains(object? value)
        {
            if (!IsCompatibleType(value!.GetType()))
                return false;
 
            return Contains((T)value);
        }
 
        int System.Collections.IList.IndexOf(object? value)
        {
            if (!IsCompatibleType(value!.GetType()))
                return -1;
 
            return IndexOf((T)value);
        }
 
        void System.Collections.IList.Insert(int index, object? value)
        {
            if (!IsCompatibleType(value!.GetType()))
                throw new ArgumentException(SR.Arg_IncompatibleParamType, nameof(value));
 
            Insert(index, (T)value);
        }
 
        void System.Collections.IList.Remove(object? value)
        {
            if (IsCompatibleType(value!.GetType()))
            {
                Remove((T)value);
            }
        }
 
 
        //-----------------------------------------------
        // Helper methods and classes
        //-----------------------------------------------
 
        private static bool IsCompatibleType(object? value)
        {
            if ((value == null && !typeof(T).IsValueType) || (value is T))
                return true;
 
            return false;
        }
    }
 
    /// <summary>
    /// Implementation of IEnumerator{T} and IEnumerator over an IList{T}.
    /// </summary>
    internal struct IListEnumerator<T> : IEnumerator<T>, System.Collections.IEnumerator
    {
        private readonly IList<T> _sequence;
        private int _index;
        private T _current;
 
        /// <summary>
        /// Constructor.
        /// </summary>
        public IListEnumerator(IList<T> sequence)
        {
            _sequence = sequence;
            _index = 0;
            _current = default(T)!;
        }
 
        /// <summary>
        /// No-op.
        /// </summary>
        public void Dispose()
        {
        }
 
        /// <summary>
        /// Return current item.  Return default value if before first item or after last item in the list.
        /// </summary>
        public T Current
        {
            get { return _current; }
        }
 
        /// <summary>
        /// Return current item.  Throw exception if before first item or after last item in the list.
        /// </summary>
        object System.Collections.IEnumerator.Current
        {
            get
            {
                if (_index == 0)
                    throw new InvalidOperationException(SR.Format(SR.Sch_EnumNotStarted, string.Empty));
 
                if (_index > _sequence.Count)
                    throw new InvalidOperationException(SR.Format(SR.Sch_EnumFinished, string.Empty));
 
                return _current!;
            }
        }
 
        /// <summary>
        /// Advance enumerator to next item in list.  Return false if there are no more items.
        /// </summary>
        public bool MoveNext()
        {
            if (_index < _sequence.Count)
            {
                _current = _sequence[_index];
                _index++;
                return true;
            }
 
            _current = default(T)!;
            return false;
        }
 
        /// <summary>
        /// Set the enumerator to its initial position, which is before the first item in the list.
        /// </summary>
        void System.Collections.IEnumerator.Reset()
        {
            _index = 0;
            _current = default(T)!;
        }
    }
}