UncheckedList.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.Diagnostics;
  6. using System.Runtime.Versioning;
  7. using System.Threading;
  8. namespace ILRuntime.Other
  9. {
  10. /// <summary>
  11. /// This is a copy of the latest .NET framework 4.5 List implementation, with all extraneous checking removed.
  12. /// </summary>
  13. /// <typeparam name="T"></typeparam>
  14. [Serializable]
  15. public class UncheckedList<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection
  16. {
  17. private const int _defaultCapacity = 4;
  18. private T[] _items;
  19. private int _size;
  20. private int _version;
  21. [NonSerialized]
  22. private Object _syncRoot;
  23. private static readonly T[] _emptyArray = new T[0];
  24. // Constructs a UncheckedList. The list is initially empty and has a capacity
  25. // of zero. Upon adding the first element to the list the capacity is
  26. // increased to _defaultCapacity, and then increased in multiples of two
  27. // as required.
  28. public UncheckedList()
  29. {
  30. _items = _emptyArray;
  31. }
  32. // Constructs a UncheckedList with a given initial capacity. The list is
  33. // initially empty, but will have room for the given number of elements
  34. // before any reallocations are required.
  35. //
  36. public UncheckedList(int capacity)
  37. {
  38. if (capacity == 0)
  39. _items = _emptyArray;
  40. else
  41. _items = new T[capacity];
  42. }
  43. // Constructs a UncheckedList, copying the contents of the given collection. The
  44. // size and capacity of the new list will both be equal to the size of the
  45. // given collection.
  46. //
  47. public UncheckedList(IEnumerable<T> collection)
  48. {
  49. ICollection<T> c = collection as ICollection<T>;
  50. if (c != null)
  51. {
  52. int count = c.Count;
  53. if (count == 0)
  54. {
  55. _items = _emptyArray;
  56. }
  57. else
  58. {
  59. _items = new T[count];
  60. c.CopyTo(_items, 0);
  61. _size = count;
  62. }
  63. }
  64. else
  65. {
  66. _size = 0;
  67. _items = _emptyArray;
  68. AddEnumerable(collection);
  69. }
  70. }
  71. // Gets and sets the capacity of this list. The capacity is the size of
  72. // the internal array used to hold items. When set, the internal
  73. // array of the list is reallocated to the given capacity.
  74. //
  75. public int Capacity
  76. {
  77. get
  78. {
  79. return _items.Length;
  80. }
  81. set
  82. {
  83. if (value != _items.Length)
  84. {
  85. if (value > 0)
  86. {
  87. T[] newItems = new T[value];
  88. if (_size > 0)
  89. {
  90. Array.Copy(_items, 0, newItems, 0, _size);
  91. }
  92. _items = newItems;
  93. }
  94. else
  95. {
  96. _items = _emptyArray;
  97. }
  98. }
  99. }
  100. }
  101. // Read-only property describing how many elements are in the UncheckedList.
  102. public int Count
  103. {
  104. get
  105. {
  106. return _size;
  107. }
  108. }
  109. bool System.Collections.IList.IsFixedSize
  110. {
  111. get { return false; }
  112. }
  113. // Is this UncheckedList read-only?
  114. bool ICollection<T>.IsReadOnly
  115. {
  116. get { return false; }
  117. }
  118. bool System.Collections.IList.IsReadOnly
  119. {
  120. get { return false; }
  121. }
  122. // Is this UncheckedList synchronized (thread-safe)?
  123. bool System.Collections.ICollection.IsSynchronized
  124. {
  125. get { return false; }
  126. }
  127. // Synchronization root for this object.
  128. Object System.Collections.ICollection.SyncRoot
  129. {
  130. get
  131. {
  132. if (_syncRoot == null)
  133. {
  134. System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
  135. }
  136. return _syncRoot;
  137. }
  138. }
  139. // Sets or Gets the element at the given index.
  140. //
  141. public T this[int index]
  142. {
  143. get
  144. {
  145. return _items[index];
  146. }
  147. set
  148. {
  149. _items[index] = value;
  150. _version++;
  151. }
  152. }
  153. private static bool IsCompatibleObject(object value)
  154. {
  155. // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
  156. // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
  157. return ((value is T) || (value == null && default(T) == null));
  158. }
  159. Object System.Collections.IList.this[int index]
  160. {
  161. get
  162. {
  163. return this[index];
  164. }
  165. set
  166. {
  167. try
  168. {
  169. this[index] = (T)value;
  170. }
  171. catch (InvalidCastException)
  172. {
  173. }
  174. }
  175. }
  176. // Adds the given object to the end of this list. The size of the list is
  177. // increased by one. If required, the capacity of the list is doubled
  178. // before adding the new element.
  179. public void Add(T item)
  180. {
  181. var array = _items;
  182. var size = _size;
  183. if ((uint)size < (uint)array.Length)
  184. {
  185. _size = size + 1;
  186. array[size] = item;
  187. }
  188. else
  189. {
  190. AddWithResize(item);
  191. }
  192. }
  193. // Non-inline from UncheckedList.Add to improve its code quality as uncommon path
  194. private void AddWithResize(T item)
  195. {
  196. var size = _size;
  197. EnsureCapacity(size + 1);
  198. _size = size + 1;
  199. _items[size] = item;
  200. }
  201. int System.Collections.IList.Add(Object item)
  202. {
  203. try
  204. {
  205. Add((T)item);
  206. }
  207. catch (InvalidCastException)
  208. {
  209. }
  210. return Count - 1;
  211. }
  212. // Adds the elements of the given collection to the end of this list. If
  213. // required, the capacity of the list is increased to twice the previous
  214. // capacity or the new size, whichever is larger.
  215. //
  216. public void AddRange(IEnumerable<T> collection)
  217. {
  218. InsertRange(_size, collection);
  219. }
  220. public ReadOnlyCollection<T> AsReadOnly()
  221. {
  222. return new ReadOnlyCollection<T>(this);
  223. }
  224. // Searches a section of the list for a given element using a binary search
  225. // algorithm. Elements of the list are compared to the search value using
  226. // the given IComparer interface. If comparer is null, elements of
  227. // the list are compared to the search value using the IComparable
  228. // interface, which in that case must be implemented by all elements of the
  229. // list and the given search value. This method assumes that the given
  230. // section of the list is already sorted; if this is not the case, the
  231. // result will be incorrect.
  232. //
  233. // The method returns the index of the given value in the list. If the
  234. // list does not contain the given value, the method returns a negative
  235. // integer. The bitwise complement operator (~) can be applied to a
  236. // negative result to produce the index of the first element (if any) that
  237. // is larger than the given search value. This is also the index at which
  238. // the search value should be inserted into the list in order for the list
  239. // to remain sorted.
  240. //
  241. // The method uses the Array.BinarySearch method to perform the
  242. // search.
  243. //
  244. public int BinarySearch(int index, int count, T item, IComparer<T> comparer)
  245. {
  246. if (index < 0) return -1;
  247. return Array.BinarySearch<T>(_items, index, count, item, comparer);
  248. }
  249. public int BinarySearch(T item)
  250. {
  251. return BinarySearch(0, Count, item, null);
  252. }
  253. public int BinarySearch(T item, IComparer<T> comparer)
  254. {
  255. return BinarySearch(0, Count, item, comparer);
  256. }
  257. // Clears the contents of UncheckedList.
  258. public void Clear()
  259. {
  260. if (!typeof(T).IsValueType)
  261. {
  262. int size = _size;
  263. _size = 0;
  264. _version++;
  265. if (size > 0)
  266. {
  267. Array.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references.
  268. }
  269. }
  270. else
  271. {
  272. _size = 0;
  273. _version++;
  274. }
  275. }
  276. // Contains returns true if the specified element is in the UncheckedList.
  277. // It does a linear, O(n) search. Equality is determined by calling
  278. // EqualityComparer<T>.Default.Equals().
  279. public bool Contains(T item)
  280. {
  281. // PERF: IndexOf calls Array.IndexOf, which internally
  282. // calls EqualityComparer<T>.Default.IndexOf, which
  283. // is specialized for different types. This
  284. // boosts performance since instead of making a
  285. // virtual method call each iteration of the loop,
  286. // via EqualityComparer<T>.Default.Equals, we
  287. // only make one virtual call to EqualityComparer.IndexOf.
  288. return _size != 0 && IndexOf(item) != -1;
  289. }
  290. bool System.Collections.IList.Contains(Object item)
  291. {
  292. if (IsCompatibleObject(item))
  293. {
  294. return Contains((T)item);
  295. }
  296. return false;
  297. }
  298. public UncheckedList<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
  299. {
  300. UncheckedList<TOutput> list = new UncheckedList<TOutput>(_size);
  301. for (int i = 0; i < _size; i++)
  302. {
  303. list._items[i] = converter(_items[i]);
  304. }
  305. list._size = _size;
  306. return list;
  307. }
  308. // Copies this UncheckedList into array, which must be of a
  309. // compatible array type.
  310. //
  311. public void CopyTo(T[] array)
  312. {
  313. CopyTo(array, 0);
  314. }
  315. // Copies this UncheckedList into array, which must be of a
  316. // compatible array type.
  317. //
  318. void System.Collections.ICollection.CopyTo(Array array, int arrayIndex)
  319. {
  320. try
  321. {
  322. // Array.Copy will check for NULL.
  323. Array.Copy(_items, 0, array, arrayIndex, _size);
  324. }
  325. catch (ArrayTypeMismatchException)
  326. {
  327. }
  328. }
  329. // Copies a section of this list to the given array at the given index.
  330. //
  331. // The method uses the Array.Copy method to copy the elements.
  332. //
  333. public void CopyTo(int index, T[] array, int arrayIndex, int count)
  334. {
  335. // Delegate rest of error checking to Array.Copy.
  336. Array.Copy(_items, index, array, arrayIndex, count);
  337. }
  338. public void CopyTo(T[] array, int arrayIndex)
  339. {
  340. // Delegate rest of error checking to Array.Copy.
  341. Array.Copy(_items, 0, array, arrayIndex, _size);
  342. }
  343. // Ensures that the capacity of this list is at least the given minimum
  344. // value. If the current capacity of the list is less than min, the
  345. // capacity is increased to twice the current capacity or to min,
  346. // whichever is larger.
  347. private void EnsureCapacity(int min)
  348. {
  349. if (_items.Length < min)
  350. {
  351. int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Length * 2;
  352. // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
  353. // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
  354. if ((uint) newCapacity > Int32.MaxValue) newCapacity = Int32.MaxValue;
  355. if (newCapacity < min) newCapacity = min;
  356. Capacity = newCapacity;
  357. }
  358. }
  359. public bool Exists(Predicate<T> match)
  360. {
  361. return FindIndex(match) != -1;
  362. }
  363. public T Find(Predicate<T> match)
  364. {
  365. for (int i = 0; i < _size; i++)
  366. {
  367. if (match(_items[i]))
  368. {
  369. return _items[i];
  370. }
  371. }
  372. return default(T);
  373. }
  374. public UncheckedList<T> FindAll(Predicate<T> match)
  375. {
  376. UncheckedList<T> list = new UncheckedList<T>();
  377. for (int i = 0; i < _size; i++)
  378. {
  379. if (match(_items[i]))
  380. {
  381. list.Add(_items[i]);
  382. }
  383. }
  384. return list;
  385. }
  386. public int FindIndex(Predicate<T> match)
  387. {
  388. return FindIndex(0, _size, match);
  389. }
  390. public int FindIndex(int startIndex, Predicate<T> match)
  391. {
  392. return FindIndex(startIndex, _size - startIndex, match);
  393. }
  394. public int FindIndex(int startIndex, int count, Predicate<T> match)
  395. {
  396. int endIndex = startIndex + count;
  397. for (int i = startIndex; i < endIndex; i++)
  398. {
  399. if (match(_items[i])) return i;
  400. }
  401. return -1;
  402. }
  403. public T FindLast(Predicate<T> match)
  404. {
  405. for (int i = _size - 1; i >= 0; i--)
  406. {
  407. if (match(_items[i]))
  408. {
  409. return _items[i];
  410. }
  411. }
  412. return default(T);
  413. }
  414. public int FindLastIndex(Predicate<T> match)
  415. {
  416. return FindLastIndex(_size - 1, _size, match);
  417. }
  418. public int FindLastIndex(int startIndex, Predicate<T> match)
  419. {
  420. return FindLastIndex(startIndex, startIndex + 1, match);
  421. }
  422. public int FindLastIndex(int startIndex, int count, Predicate<T> match)
  423. {
  424. int endIndex = startIndex - count;
  425. for (int i = startIndex; i > endIndex; i--)
  426. {
  427. if (match(_items[i]))
  428. {
  429. return i;
  430. }
  431. }
  432. return -1;
  433. }
  434. public void ForEach(Action<T> action)
  435. {
  436. int version = _version;
  437. for (int i = 0; i < _size; i++)
  438. {
  439. if (version != _version)
  440. {
  441. break;
  442. }
  443. action(_items[i]);
  444. }
  445. }
  446. // Returns an enumerator for this list with the given
  447. // permission for removal of elements. If modifications made to the list
  448. // while an enumeration is in progress, the MoveNext and
  449. // GetObject methods of the enumerator will throw an exception.
  450. //
  451. public Enumerator GetEnumerator()
  452. {
  453. return new Enumerator(this);
  454. }
  455. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  456. {
  457. return new Enumerator(this);
  458. }
  459. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  460. {
  461. return new Enumerator(this);
  462. }
  463. public UncheckedList<T> GetRange(int index, int count)
  464. {
  465. UncheckedList<T> list = new UncheckedList<T>(count);
  466. Array.Copy(_items, index, list._items, 0, count);
  467. list._size = count;
  468. return list;
  469. }
  470. // Returns the index of the first occurrence of a given value in a range of
  471. // this list. The list is searched forwards from beginning to end.
  472. // The elements of the list are compared to the given value using the
  473. // Object.Equals method.
  474. //
  475. // This method uses the Array.IndexOf method to perform the
  476. // search.
  477. //
  478. public int IndexOf(T item)
  479. {
  480. return Array.IndexOf(_items, item, 0, _size);
  481. }
  482. int System.Collections.IList.IndexOf(Object item)
  483. {
  484. if (IsCompatibleObject(item))
  485. {
  486. return IndexOf((T)item);
  487. }
  488. return -1;
  489. }
  490. // Returns the index of the first occurrence of a given value in a range of
  491. // this list. The list is searched forwards, starting at index
  492. // index and ending at count number of elements. The
  493. // elements of the list are compared to the given value using the
  494. // Object.Equals method.
  495. //
  496. // This method uses the Array.IndexOf method to perform the
  497. // search.
  498. //
  499. public int IndexOf(T item, int index)
  500. {
  501. return Array.IndexOf(_items, item, index, _size - index);
  502. }
  503. // Returns the index of the first occurrence of a given value in a range of
  504. // this list. The list is searched forwards, starting at index
  505. // index and upto count number of elements. The
  506. // elements of the list are compared to the given value using the
  507. // Object.Equals method.
  508. //
  509. // This method uses the Array.IndexOf method to perform the
  510. // search.
  511. //
  512. public int IndexOf(T item, int index, int count)
  513. {
  514. return Array.IndexOf(_items, item, index, count);
  515. }
  516. // Inserts an element into this list at a given index. The size of the list
  517. // is increased by one. If required, the capacity of the list is doubled
  518. // before inserting the new element.
  519. //
  520. public void Insert(int index, T item)
  521. {
  522. if (_size == _items.Length) EnsureCapacity(_size + 1);
  523. if (index < _size)
  524. {
  525. Array.Copy(_items, index, _items, index + 1, _size - index);
  526. }
  527. _items[index] = item;
  528. _size++;
  529. _version++;
  530. }
  531. void System.Collections.IList.Insert(int index, Object item)
  532. {
  533. try
  534. {
  535. Insert(index, (T)item);
  536. }
  537. catch (InvalidCastException)
  538. {
  539. }
  540. }
  541. // Inserts the elements of the given collection at a given index. If
  542. // required, the capacity of the list is increased to twice the previous
  543. // capacity or the new size, whichever is larger. Ranges may be added
  544. // to the end of the list by setting index to the UncheckedList's size.
  545. //
  546. public void InsertRange(int index, IEnumerable<T> collection)
  547. {
  548. ICollection<T> c = collection as ICollection<T>;
  549. if (c != null)
  550. { // if collection is ICollection<T>
  551. int count = c.Count;
  552. if (count > 0)
  553. {
  554. EnsureCapacity(_size + count);
  555. if (index < _size)
  556. {
  557. Array.Copy(_items, index, _items, index + count, _size - index);
  558. }
  559. // If we're inserting a UncheckedList into itself, we want to be able to deal with that.
  560. if (this == c)
  561. {
  562. // Copy first part of _items to insert location
  563. Array.Copy(_items, 0, _items, index, index);
  564. // Copy last part of _items back to inserted location
  565. Array.Copy(_items, index + count, _items, index * 2, _size - index);
  566. }
  567. else
  568. {
  569. c.CopyTo(_items, index);
  570. }
  571. _size += count;
  572. }
  573. }
  574. else if (index < _size)
  575. {
  576. // We're inserting a lazy enumerable. Call Insert on each of the constituent items.
  577. using (IEnumerator<T> en = collection.GetEnumerator())
  578. {
  579. while (en.MoveNext())
  580. {
  581. Insert(index++, en.Current);
  582. }
  583. }
  584. }
  585. else
  586. {
  587. // We're adding a lazy enumerable because the index is at the end of this list.
  588. AddEnumerable(collection);
  589. }
  590. _version++;
  591. }
  592. // Returns the index of the last occurrence of a given value in a range of
  593. // this list. The list is searched backwards, starting at the end
  594. // and ending at the first element in the list. The elements of the list
  595. // are compared to the given value using the Object.Equals method.
  596. //
  597. // This method uses the Array.LastIndexOf method to perform the
  598. // search.
  599. //
  600. public int LastIndexOf(T item)
  601. {
  602. if (_size == 0)
  603. { // Special case for empty list
  604. return -1;
  605. }
  606. else
  607. {
  608. return LastIndexOf(item, _size - 1, _size);
  609. }
  610. }
  611. // Returns the index of the last occurrence of a given value in a range of
  612. // this list. The list is searched backwards, starting at index
  613. // index and ending at the first element in the list. The
  614. // elements of the list are compared to the given value using the
  615. // Object.Equals method.
  616. //
  617. // This method uses the Array.LastIndexOf method to perform the
  618. // search.
  619. //
  620. public int LastIndexOf(T item, int index)
  621. {
  622. return LastIndexOf(item, index, index + 1);
  623. }
  624. // Returns the index of the last occurrence of a given value in a range of
  625. // this list. The list is searched backwards, starting at index
  626. // index and upto count elements. The elements of
  627. // the list are compared to the given value using the Object.Equals
  628. // method.
  629. //
  630. // This method uses the Array.LastIndexOf method to perform the
  631. // search.
  632. //
  633. public int LastIndexOf(T item, int index, int count)
  634. {
  635. if (_size == 0)
  636. { // Special case for empty list
  637. return -1;
  638. }
  639. return Array.LastIndexOf(_items, item, index, count);
  640. }
  641. // Removes the element at the given index. The size of the list is
  642. // decreased by one.
  643. //
  644. public bool Remove(T item)
  645. {
  646. int index = IndexOf(item);
  647. if (index >= 0)
  648. {
  649. RemoveAt(index);
  650. return true;
  651. }
  652. return false;
  653. }
  654. void System.Collections.IList.Remove(Object item)
  655. {
  656. if (IsCompatibleObject(item))
  657. {
  658. Remove((T)item);
  659. }
  660. }
  661. // This method removes all items which matches the predicate.
  662. // The complexity is O(n).
  663. public int RemoveAll(Predicate<T> match)
  664. {
  665. int freeIndex = 0; // the first free slot in items array
  666. // Find the first item which needs to be removed.
  667. while (freeIndex < _size && !match(_items[freeIndex])) freeIndex++;
  668. if (freeIndex >= _size) return 0;
  669. int current = freeIndex + 1;
  670. while (current < _size)
  671. {
  672. // Find the first item which needs to be kept.
  673. while (current < _size && match(_items[current])) current++;
  674. if (current < _size)
  675. {
  676. // copy item to the free slot.
  677. _items[freeIndex++] = _items[current++];
  678. }
  679. }
  680. if (!typeof(T).IsValueType)
  681. {
  682. Array.Clear(_items, freeIndex, _size - freeIndex); // Clear the elements so that the gc can reclaim the references.
  683. }
  684. int result = _size - freeIndex;
  685. _size = freeIndex;
  686. _version++;
  687. return result;
  688. }
  689. // Removes the element at the given index. The size of the list is
  690. // decreased by one.
  691. //
  692. public void RemoveAt(int index)
  693. {
  694. _size--;
  695. if (index < _size)
  696. {
  697. Array.Copy(_items, index + 1, _items, index, _size - index);
  698. }
  699. #if DEBUG
  700. _items[_size] = default(T);
  701. #endif
  702. }
  703. // Removes a range of elements from this list.
  704. //
  705. public void RemoveRange(int index, int count)
  706. {
  707. if (count > 0)
  708. {
  709. int i = _size;
  710. _size -= count;
  711. if (index < _size)
  712. {
  713. Array.Copy(_items, index + count, _items, index, _size - index);
  714. }
  715. #if DEBUG
  716. Array.Clear(_items, _size, count);
  717. #endif
  718. }
  719. }
  720. // Reverses the elements in this list.
  721. public void Reverse()
  722. {
  723. Reverse(0, Count);
  724. }
  725. // Reverses the elements in a range of this list. Following a call to this
  726. // method, an element in the range given by index and count
  727. // which was previously located at index i will now be located at
  728. // index index + (index + count - i - 1).
  729. //
  730. public void Reverse(int index, int count)
  731. {
  732. if (count > 1)
  733. {
  734. Array.Reverse(_items, index, count);
  735. }
  736. _version++;
  737. }
  738. // Sorts the elements in this list. Uses the default comparer and
  739. // Array.Sort.
  740. public void Sort()
  741. {
  742. Sort(0, Count, null);
  743. }
  744. // Sorts the elements in this list. Uses Array.Sort with the
  745. // provided comparer.
  746. public void Sort(IComparer<T> comparer)
  747. {
  748. Sort(0, Count, comparer);
  749. }
  750. // Sorts the elements in a section of this list. The sort compares the
  751. // elements to each other using the given IComparer interface. If
  752. // comparer is null, the elements are compared to each other using
  753. // the IComparable interface, which in that case must be implemented by all
  754. // elements of the list.
  755. //
  756. // This method uses the Array.Sort method to sort the elements.
  757. //
  758. public void Sort(int index, int count, IComparer<T> comparer)
  759. {
  760. if (count > 1)
  761. {
  762. Array.Sort<T>(_items, index, count, comparer);
  763. }
  764. _version++;
  765. }
  766. public void Sort(Comparison<T> comparison)
  767. {
  768. throw new NotImplementedException();
  769. /*if (_size > 1)
  770. {
  771. ArraySortHelper<T>.Sort(_items, 0, _size, comparison);
  772. }
  773. _version++;*/
  774. }
  775. // ToArray returns an array containing the contents of the UncheckedList.
  776. // This requires copying the UncheckedList, which is an O(n) operation.
  777. public T[] ToArray()
  778. {
  779. if (_size == 0)
  780. {
  781. return _emptyArray;
  782. }
  783. T[] array = new T[_size];
  784. Array.Copy(_items, 0, array, 0, _size);
  785. return array;
  786. }
  787. // Sets the capacity of this list to the size of the list. This method can
  788. // be used to minimize a list's memory overhead once it is known that no
  789. // new elements will be added to the list. To completely clear a list and
  790. // release all memory referenced by the list, execute the following
  791. // statements:
  792. //
  793. // list.Clear();
  794. // list.TrimExcess();
  795. //
  796. public void TrimExcess()
  797. {
  798. int threshold = (int)(((double)_items.Length) * 0.9);
  799. if (_size < threshold)
  800. {
  801. Capacity = _size;
  802. }
  803. }
  804. public bool TrueForAll(Predicate<T> match)
  805. {
  806. for (int i = 0; i < _size; i++)
  807. {
  808. if (!match(_items[i]))
  809. {
  810. return false;
  811. }
  812. }
  813. return true;
  814. }
  815. private void AddEnumerable(IEnumerable<T> enumerable)
  816. {
  817. Debug.Assert(enumerable != null);
  818. Debug.Assert(!(enumerable is ICollection<T>), "We should have optimized for this beforehand.");
  819. using (IEnumerator<T> en = enumerable.GetEnumerator())
  820. {
  821. _version++; // Even if the enumerable has no items, we can update _version.
  822. while (en.MoveNext())
  823. {
  824. // Capture Current before doing anything else. If this throws
  825. // an exception, we want to make a clean break.
  826. T current = en.Current;
  827. if (_size == _items.Length)
  828. {
  829. EnsureCapacity(_size + 1);
  830. }
  831. _items[_size++] = current;
  832. }
  833. }
  834. }
  835. public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
  836. {
  837. private UncheckedList<T> list;
  838. private int index;
  839. private int version;
  840. private T current;
  841. internal Enumerator(UncheckedList<T> list)
  842. {
  843. this.list = list;
  844. index = 0;
  845. version = list._version;
  846. current = default(T);
  847. }
  848. public void Dispose()
  849. {
  850. }
  851. public bool MoveNext()
  852. {
  853. UncheckedList<T> localUncheckedList = list;
  854. if (version == localUncheckedList._version && ((uint)index < (uint)localUncheckedList._size))
  855. {
  856. current = localUncheckedList._items[index];
  857. index++;
  858. return true;
  859. }
  860. return MoveNextRare();
  861. }
  862. private bool MoveNextRare()
  863. {
  864. index = list._size + 1;
  865. current = default(T);
  866. return false;
  867. }
  868. public T Current
  869. {
  870. get
  871. {
  872. return current;
  873. }
  874. }
  875. Object System.Collections.IEnumerator.Current
  876. {
  877. get
  878. {
  879. return Current;
  880. }
  881. }
  882. void System.Collections.IEnumerator.Reset()
  883. {
  884. index = 0;
  885. current = default(T);
  886. }
  887. }
  888. }
  889. }