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

来源:互联网 发布:杂志虫软件 编辑:程序博客网 时间:2024/05/03 00:58

类代码

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));        }


原创粉丝点击