使用Array的一个扩展类,允许Add,Remove,Contains

类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace DevGuideToCollections
{
    /// <summary>
    /// Represents a strongly typed array.
    /// </summary>
    /// <typeparam name="T">Specifies the type of elements in the array.</typeparam>
    [DebuggerDisplay("Count={Count}")]
    [DebuggerTypeProxy(typeof(ArrayDebugView))]
    public class ArrayEx<T>
    {
        const int GROW_BY = 10;

        // Internal variable for holding the array information
        T[] m_data;
        // Contains the number of elements in the array.
        int m_count;
        int m_updateCode;

        /// <summary>
        /// Initializes a new instance of the ArrayEx(T) class that is empty.
        /// </summary>
        public ArrayEx()
        {
            Initialize(GROW_BY);
        }

        /// <summary>
        /// Initializes a new instance of the ArrayEx(T) class that contains the items in the array.
        /// </summary>
        /// <param name="items">Adds items to the ArrayEx(T).</param>
        public ArrayEx(IEnumerable<T> items)
        {
            Initialize(GROW_BY);

            foreach (T item in items)
            {
                Add(item);
            }
        }
    
        /// <summary>
        /// Initializes a new instance of the ArrayEx(T) class that is empty and has the specified initial capacity.
        /// </summary>
        /// <param name="capacity">The number of elements that the new array can initially store.</param>
        public ArrayEx(int capacity)
        {
            Initialize(capacity);
        }

        void Initialize(int capacity)
        {
            m_data = new T[capacity];
        }

        /// <summary>
        /// States if the ArrayEx(T) is empty.
        /// </summary>
        public bool IsEmpty
        {
            get { return m_count <= 0; }
        }


        /// <summary>
        /// Gets the number of elements actually contained in the ArrayEx(T).
        /// </summary>
        public int Count
        {
            get { return m_count; }
        }

        /// <summary>
        /// Gets or sets the size of the internal data array.
        /// </summary>
        public int Capacity
        {
            get { return m_data.Length; }
            set
            {
                // We do not support truncating the stored array. So throw an exception if the array is less than Count.
                if (value < Count)
                {
                    throw new ArgumentOutOfRangeException("value", "The value is less than Count");
                }

                // We do not need to do anything if the newly specified capacity is the same as the old one.
                if (value == Capacity)
                {
                    return;
                }

                // We will need to create a new array and move all of the values in the old array to the new one
                T[] tmp = new T[value];

                for (int i = 0; i < Count; ++i)
                {
                    tmp[i] = m_data[i];
                }

                m_data = tmp;
                ++m_updateCode;
            }
        }

        /// <summary>
        /// Adds an object to the end of the ArrayEx(T).
        /// </summary>
        /// <param name="item">The item to add to the end of the ArrayEx(T).</param>
        public void Add(T item)
        {
            if (m_data.Length <= m_count)
            {
                Capacity += GROW_BY;
            }

            // We will need to assign the item to the last element and then increment the count variable
            m_data[m_count++] = item;
            ++m_updateCode;
        }

        /// <summary>
        /// Checks to see if the item is present in the ArrayEx(T).
        /// </summary>
        /// <param name="item">The item to see if the array contains.</param>
        /// <returns>True if the item is in the array, false if it is not.</returns>
        public bool Contains(T item)
        {
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            for (int i = 0; i < m_count; i++)
            {
                if (comparer.Equals(m_data[i], item))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Gets the index of the specified item.
        /// </summary>
        /// <param name="item">The item to get the index of.</param>
        /// <returns>-1 if the item isn't found in the array, the index of the found item otherwise.</returns>
        public int IndexOf(T item)
        {
            return Array.IndexOf<T>(m_data, item, 0, m_count);
        }

        /// <summary>
        /// Clears all values from the ArrayEx(T).
        /// </summary>
        public void Clear()
        {
            Array.Clear(m_data, 0, m_count);
            ++m_updateCode;
            m_count = 0;
        }

        /// <summary>
        /// Removes the first occurrence of the specified item from the ArrayEx(T).
        /// </summary>
        /// <param name="item">The item to remove from the ArrayEx(T).</param>
        /// <returns>True if an item was removed, false otherwise.</returns>
        public bool Remove(T item)
        {
            return Remove(item, false);
        }

        /// <summary>
        /// Removes the first or all occurrences of the specified item from the ArrayEx(T).
        /// </summary>
        /// <param name="item">The item to remove from the ArrayEx(T).</param>
        /// <param name="alloccurrences">True if all occurrences of the item should be removed, False if only the first should be removed.</param>
        /// <returns>True if an item was removed, false otherwise.</returns>
        public bool Remove(T item, bool alloccurrences)
        {
            int shiftto = 0;
            bool shiftmode = false;
            bool removed = false;

            int count = m_count;
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;

            for (int i = 0; i < count; ++i)
            {

                if (comparer.Equals(m_data[i], item) && (alloccurrences || !shiftmode))
                {
                    // Decrement the count since we have found an instance
                    --m_count;
                    removed = true;

                    // Check to see if we have already found one occurrence of the item we are removing
                    if (!shiftmode)
                    {
                        // We will start shifting to the position of the first occurrence.
                        shiftto = i;
                        // Enable shifting
                        shiftmode = true;
                    }

                    continue;
                }

                if (shiftmode)
                {
                    // Since we are shifting elements we need to shift the element down and then update the shiftto index to the next element.
                    m_data[shiftto++] = m_data[i];
                }
            }

            for (int i = m_count; i < count; ++i)
            {
                m_data[i] = default(T);
            }

            if (removed)
            {
                ++m_updateCode;
            }

            return removed;
        }

        /// <summary>
        /// Removes the item located at the specified index.
        /// </summary>
        /// <param name="index">The index of the item to remove</param>
        public void RemoveAt(int index)
        {
            if (index < 0 || index >= m_count)
            {
                // Item has already been removed.
                return;
            }

            int count = Count;

            // Shift all of the elements after the specified index down one.
            for (int i = index + 1; i < count; ++i)
            {
                m_data[i - 1] = m_data[i];
            }

            // Decrement the count to reflect the item being removed.
            --m_count;
            ++m_updateCode;

            m_data[m_count] = default(T);
        }

        /// <summary>
        /// Inserts an item into the ArrayEx(T) at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which item should be inserted.</param>
        /// <param name="item">The item to insert.</param>
        public void Insert(int index, T item)
        {
            if (index < 0 || index >= m_count)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            if (m_count + 1 >= Capacity)
            {
                Capacity = m_count + GROW_BY;
            }

            // First we need to shift all elements at the location up by one
            for (int i = m_count; i > index && i > 0; --i)
            {
                m_data[i] = m_data[i - 1];
            }

            m_data[index] = item;

            ++m_count;
            ++m_updateCode;
        }

        /// <summary>
        /// Gets or sets an element in the ArrayEx(T).
        /// </summary>
        /// <param name="index">The index of the element.</param>
        /// <returns>The value of the element.</returns>
        public T this[int index]
        {
            get
            {
                if (index < 0 || index >= m_count)
                {
                    throw new ArgumentOutOfRangeException("index");
                }

                return m_data[index];
            }
            set
            {
                if (index < 0 || index >= m_count)
                {
                    throw new ArgumentOutOfRangeException("index");
                }

                m_data[index] = value;
                ++m_updateCode;
            }
        }

        /// <summary>
        /// Copies the elements of the ArrayEx(T) to a new array.
        /// </summary>
        /// <returns>An array containing copies of the elements of the ArrayEx(T).</returns>
        public T[] ToArray()
        {
            T[] tmp = new T[Count];

            for (int i = 0; i < Count; ++i)
            {
                tmp[i] = m_data[i];
            }

            return tmp;
        }
    }
}

测试方法

        public static void TestArrayEx()
        {
            // Check null indexing
            ArrayEx<ArrayEx<int>> nullableList = new ArrayEx<ArrayEx<int>>();
            nullableList = new ArrayEx<ArrayEx<int>>();
            ArrayEx<int> tmpList = new ArrayEx<int>();
            nullableList.Add(new ArrayEx<int>());
            nullableList.Add(null);
            nullableList.Add(new ArrayEx<int>());
            nullableList.Add(null);
            nullableList.Add(tmpList);
            nullableList.Add(null);
            System.Diagnostics.Debug.Assert(nullableList.Contains(null));
            System.Diagnostics.Debug.Assert(nullableList.Contains(tmpList));
            System.Diagnostics.Debug.Assert(!nullableList.Contains(new ArrayEx<int>()));

            ArrayEx<int> list = new ArrayEx<int>();

            // Testing the add
            list.Add(1);
            list.Add(3);
            list.Add(4);
            list.Add(6);
            list.Add(9);
            list.Add(5);
            list.Add(6);
            list.Add(9);
            list.Add(9);
            list.Add(7);

            List<int> tt = new List<int>(new int[] {1, 3, 4}) ;
            System.Diagnostics.Debug.Assert(list.Count == 10);

            // Testing the grow by
            list.Add(14);
            list.Add(19);
            System.Diagnostics.Debug.Assert(list.Count == 12);

            // Deleting the first 6 from the list
            list.Remove(6, false);
            System.Diagnostics.Debug.Assert(list.Contains(6));
            System.Diagnostics.Debug.Assert(list.IndexOf(6) == 5);
            System.Diagnostics.Debug.Assert(list.Count == 11);

            // Deleting all 9s from the list
            list.Remove(9, true);
            System.Diagnostics.Debug.Assert(!list.Contains(9));
            System.Diagnostics.Debug.Assert(list.Count == 8);

            // Inserting a two at the 2nd position
            list.Insert(1, 2);
            System.Diagnostics.Debug.Assert(list[1] == 2);
            System.Diagnostics.Debug.Assert(list[2] == 3);
            System.Diagnostics.Debug.Assert(list.Count == 9);

            // Check the DebugView method
            ArrayDebugView view = new ArrayDebugView(list);
            object[] values = view.Items;
            System.Diagnostics.Debug.Assert(values.Length == list.Count);
            for (int i = 0; i < list.Count; ++i)
            {
                System.Diagnostics.Debug.Assert((int)values[i] == list[i]);
            }

            // Testing clear
            list.Clear();
            System.Diagnostics.Debug.Assert(list.Count == 0);
            list.Add(66);
            list.Add(99);
            System.Diagnostics.Debug.Assert(list[0] == 66);
            System.Diagnostics.Debug.Assert(list[1] == 99);

            // Test removing
            System.Diagnostics.Debug.Assert(list.Remove(66));
            System.Diagnostics.Debug.Assert(!list.Remove(68));

            // Prepare for RemoveAt test
            list.Clear();
            list.Add(0);
            list.Add(1);
            list.Add(2);
            list.Add(3);
            list.Add(4);
            list.Add(5);
            list.Add(6);
            list.Add(7);
            System.Diagnostics.Debug.Assert(list.Count == 8);

            // Test RemoveAt the end
            list.RemoveAt(7);
            System.Diagnostics.Debug.Assert(list.Count == 7);
            System.Diagnostics.Debug.Assert(list.Contains(6));
            System.Diagnostics.Debug.Assert(!list.Contains(7));

            // Test RemoveAt the middle
            list.RemoveAt(4);
            System.Diagnostics.Debug.Assert(list.Count == 6);
            System.Diagnostics.Debug.Assert(list.Contains(3));
            System.Diagnostics.Debug.Assert(list.Contains(5));
            System.Diagnostics.Debug.Assert(!list.Contains(4));

            // Test RemoveAt the front
            list.RemoveAt(0);
            System.Diagnostics.Debug.Assert(list.Count == 5);
            System.Diagnostics.Debug.Assert(list.Contains(1));
            System.Diagnostics.Debug.Assert(!list.Contains(0));
        }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值