//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 Tasharen Entertainment //---------------------------------------------- using UnityEngine; using System.Collections.Generic; using System.Diagnostics; /// /// This improved version of the System.Collections.Generic.List that doesn't release the buffer on Clear(), /// resulting in better performance and less garbage collection. /// PRO: BetterList performs faster than List when you Add and Remove items (although slower if you remove from the beginning). /// CON: BetterList performs worse when sorting the list. If your operations involve sorting, use the standard List instead. /// public class ObjDisOrderList where T : Object { /// /// 索引改变回调函数 /// private IndexChangeFunc _indexChangeFunc; /// /// Direct access to the buffer. Note that you should not use its 'Length' parameter, but instead use BetterList.size. /// private T[] _buffer; public T[] buffer { get { return _buffer; } } /// /// Direct access to the buffer's size. Note that it's only public for speed and efficiency. You shouldn't modify it. /// public int size = 0; public ObjDisOrderList() { } public ObjDisOrderList(int capacity) { _buffer = new T[capacity]; } /// /// For 'foreach' functionality. /// /// [DebuggerHidden] [DebuggerStepThrough] public IEnumerator GetEnumerator () { if (_buffer != null) { for (int i = 0; i < size; ++i) { yield return _buffer[i]; } } } /// /// Convenience function. I recommend using .buffer instead. /// [DebuggerHidden] public T this[int i] { get { return _buffer[i]; } set { var oldValue = _buffer[i]; if(oldValue != value) { _buffer[i] = value; //移除老的 DoIndexChanged(oldValue, -1); //添加新的 DoIndexChanged(value, i); } } } /// /// Helper function that expands the size of the array, maintaining the content. /// void AllocateMore () { T[] newList = (_buffer != null) ? new T[Mathf.Max(_buffer.Length << 1, 32)] : new T[32]; if (_buffer != null && size > 0) _buffer.CopyTo(newList, 0); _buffer = newList; } /// /// Trim the unnecessary memory, resizing the buffer to be of 'Length' size. /// Call this function only if you are sure that the buffer won't need to resize anytime soon. /// void Trim () { if (size > 0) { if (size < _buffer.Length) { T[] newList = new T[size]; for (int i = 0; i < size; ++i) newList[i] = _buffer[i]; _buffer = newList; } } else _buffer = null; } /// /// Clear the array by resetting its size to zero. Note that the memory is not actually released. /// public void Clear () { size = 0; } /// /// Clear the array and release the used memory. /// public void Release () { size = 0; _buffer = null; } /// /// Add the specified item to the end of the list. /// public void Add (T item) { if (_buffer == null || size == _buffer.Length) AllocateMore(); _buffer[size] = item; //添加新的 DoIndexChanged(item, size); ++size; } /// /// Returns 'true' if the specified item is within the list. /// public bool Contains (T item) { if (_buffer == null) return false; var hashCode = item.GetHashCode(); for (int i = 0; i < size; ++i) { if (_buffer[i].GetHashCode() == hashCode) { return true; } } return false; } /// /// Return the index of the specified item. /// public int IndexOf (T item) { if (_buffer == null) return -1; var hashCode = item.GetHashCode(); for (int i = 0; i < size; ++i) { if (_buffer[i].GetHashCode() == hashCode) { return i; } } return -1; } /// /// Remove the specified item from the list. Note that RemoveAt() is faster and is advisable if you already know the index. /// public bool Remove (T item) { if (_buffer != null && item != null) { var hashCode = item.GetHashCode(); for (int i = 0; i < size; ++i) { if (_buffer[i].GetHashCode() == hashCode) { --size; DoIndexChanged(_buffer[i], -1); //将最后一个元素放入此位置 _buffer[i] = _buffer[size]; DoIndexChanged(_buffer[i], i); _buffer[size] = default(T); return true; } } } return false; } /// /// Remove an item at the specified index. /// public void RemoveAt (int index) { if (_buffer != null && index > -1 && index < size) { --size; DoIndexChanged(_buffer[index], -1); //将最后一个元素放入此位置 _buffer[index] = _buffer[size]; DoIndexChanged(_buffer[index], index); _buffer[size] = default(T); } } /// /// Mimic List's ToArray() functionality, except that in this case the list is resized to match the current size. /// public T[] ToArray () { Trim(); return _buffer; } /// /// 索引改变回调函数 /// public void SetIndexChangeFunc(IndexChangeFunc func) { _indexChangeFunc = func; } private void DoIndexChanged(T item, int index) { if(_indexChangeFunc != null) { _indexChangeFunc(item, index); } } /// /// 索引改变回调 /// /// /// public delegate void IndexChangeFunc (T item, int index); }