Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.28 KB | None | 0 0
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. /*=============================================================================
  7. **
  8. ** Class: Queue
  9. **
  10. ** Purpose: A circular-array implementation of a generic queue.
  11. **
  12. ** Date: January 28, 2003
  13. **
  14. =============================================================================*/
  15. namespace System.Collections.Generic {
  16. using System;
  17. using System.Diagnostics;
  18. using System.Diagnostics.CodeAnalysis;
  19. using System.Security.Permissions;
  20.  
  21. // A simple Queue of generic objects. Internally it is implemented as a
  22. // circular buffer, so Enqueue can be O(n). Dequeue is O(1).
  23. [DebuggerTypeProxy(typeof(System_QueueDebugView<>))]
  24. [DebuggerDisplay("Count = {Count}")]
  25. #if !SILVERLIGHT
  26. [Serializable()]
  27. #endif
  28. [System.Runtime.InteropServices.ComVisible(false)]
  29. public class Queue<T> : IEnumerable<T>,
  30. System.Collections.ICollection,
  31. IReadOnlyCollection<T> {
  32. private T[] _array;
  33. private int _head; // First valid element in the queue
  34. private int _tail; // Last valid element in the queue
  35. private int _size; // Number of elements.
  36. private int _version;
  37. #if !SILVERLIGHT
  38. [NonSerialized]
  39. #endif
  40. private Object _syncRoot;
  41.  
  42. private const int _MinimumGrow = 4;
  43. private const int _ShrinkThreshold = 32;
  44. private const int _GrowFactor = 200; // double each time
  45. private const int _DefaultCapacity = 4;
  46. static T[] _emptyArray = new T[0];
  47.  
  48. // Creates a queue with room for capacity objects. The default initial
  49. // capacity and grow factor are used.
  50. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue"]/*' />
  51. public Queue() {
  52. _array = _emptyArray;
  53. }
  54.  
  55. // Creates a queue with room for capacity objects. The default grow factor
  56. // is used.
  57. //
  58. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue1"]/*' />
  59. public Queue(int capacity) {
  60. if (capacity < 0)
  61. ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNumRequired);
  62.  
  63. _array = new T[capacity];
  64. _head = 0;
  65. _tail = 0;
  66. _size = 0;
  67. }
  68.  
  69. // Fills a Queue with the elements of an ICollection. Uses the enumerator
  70. // to get each of the elements.
  71. //
  72. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue3"]/*' />
  73. public Queue(IEnumerable<T> collection)
  74. {
  75. if (collection == null)
  76. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
  77.  
  78. _array = new T[_DefaultCapacity];
  79. _size = 0;
  80. _version = 0;
  81.  
  82. using(IEnumerator<T> en = collection.GetEnumerator()) {
  83. while(en.MoveNext()) {
  84. Enqueue(en.Current);
  85. }
  86. }
  87. }
  88.  
  89.  
  90. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Count"]/*' />
  91. public int Count {
  92. get { return _size; }
  93. }
  94.  
  95. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.IsSynchronized"]/*' />
  96. bool System.Collections.ICollection.IsSynchronized {
  97. get { return false; }
  98. }
  99.  
  100. Object System.Collections.ICollection.SyncRoot {
  101. get {
  102. if( _syncRoot == null) {
  103. System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
  104. }
  105. return _syncRoot;
  106. }
  107. }
  108.  
  109. // Removes all Objects from the queue.
  110. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Clear"]/*' />
  111. public void Clear() {
  112. if (_head < _tail)
  113. Array.Clear(_array, _head, _size);
  114. else {
  115. Array.Clear(_array, _head, _array.Length - _head);
  116. Array.Clear(_array, 0, _tail);
  117. }
  118.  
  119. _head = 0;
  120. _tail = 0;
  121. _size = 0;
  122. _version++;
  123. }
  124.  
  125. // CopyTo copies a collection into an Array, starting at a particular
  126. // index into the array.
  127. //
  128. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.CopyTo"]/*' />
  129. public void CopyTo(T[] array, int arrayIndex)
  130. {
  131. if (array==null) {
  132. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
  133. }
  134.  
  135. if (arrayIndex < 0 || arrayIndex > array.Length) {
  136. ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_Index);
  137. }
  138.  
  139. int arrayLen = array.Length;
  140. if (arrayLen - arrayIndex < _size) {
  141. ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
  142. }
  143.  
  144. int numToCopy = (arrayLen - arrayIndex < _size) ? (arrayLen - arrayIndex) : _size;
  145. if (numToCopy == 0) return;
  146.  
  147. int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy;
  148. Array.Copy(_array, _head, array, arrayIndex, firstPart);
  149. numToCopy -= firstPart;
  150. if (numToCopy > 0) {
  151. Array.Copy(_array, 0, array, arrayIndex+_array.Length - _head, numToCopy);
  152. }
  153. }
  154.  
  155. void System.Collections.ICollection.CopyTo(Array array, int index)
  156. {
  157. if (array == null) {
  158. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
  159. }
  160.  
  161. if (array.Rank != 1) {
  162. ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
  163. }
  164.  
  165. if( array.GetLowerBound(0) != 0 ) {
  166. ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
  167. }
  168.  
  169. int arrayLen = array.Length;
  170. if (index < 0 || index > arrayLen) {
  171. ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
  172. }
  173.  
  174. if (arrayLen - index < _size) {
  175. ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
  176. }
  177.  
  178. int numToCopy = (arrayLen-index < _size) ? arrayLen-index : _size;
  179. if (numToCopy == 0) return;
  180.  
  181. try {
  182. int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy;
  183. Array.Copy(_array, _head, array, index, firstPart);
  184. numToCopy -= firstPart;
  185.  
  186. if (numToCopy > 0) {
  187. Array.Copy(_array, 0, array, index+_array.Length - _head, numToCopy);
  188. }
  189. }
  190. catch(ArrayTypeMismatchException) {
  191. ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
  192. }
  193. }
  194.  
  195. // Adds item to the tail of the queue.
  196. //
  197. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Enqueue"]/*' />
  198. public void Enqueue(T item) {
  199. if (_size == _array.Length) {
  200. int newcapacity = (int)((long)_array.Length * (long)_GrowFactor / 100);
  201. if (newcapacity < _array.Length + _MinimumGrow) {
  202. newcapacity = _array.Length + _MinimumGrow;
  203. }
  204. SetCapacity(newcapacity);
  205. }
  206.  
  207. _array[_tail] = item;
  208. _tail = (_tail + 1) % _array.Length;
  209. _size++;
  210. _version++;
  211. }
  212.  
  213. // GetEnumerator returns an IEnumerator over this Queue. This
  214. // Enumerator will support removing.
  215. //
  216. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.GetEnumerator"]/*' />
  217. public Enumerator GetEnumerator()
  218. {
  219. return new Enumerator(this);
  220. }
  221.  
  222. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.IEnumerable.GetEnumerator"]/*' />
  223. /// <internalonly/>
  224. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  225. {
  226. return new Enumerator(this);
  227. }
  228.  
  229. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  230. {
  231. return new Enumerator(this);
  232. }
  233.  
  234. // Removes the object at the head of the queue and returns it. If the queue
  235. // is empty, this method simply returns null.
  236. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Dequeue"]/*' />
  237. public T Dequeue() {
  238. if (_size == 0)
  239. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
  240.  
  241. T removed = _array[_head];
  242. _array[_head] = default(T);
  243. _head = (_head + 1) % _array.Length;
  244. _size--;
  245. _version++;
  246. return removed;
  247. }
  248.  
  249. // Returns the object at the head of the queue. The object remains in the
  250. // queue. If the queue is empty, this method throws an
  251. // InvalidOperationException.
  252. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Peek"]/*' />
  253. public T Peek() {
  254. if (_size == 0)
  255. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
  256.  
  257. return _array[_head];
  258. }
  259.  
  260. // Returns true if the queue contains at least one object equal to item.
  261. // Equality is determined using item.Equals().
  262. //
  263. // Exceptions: ArgumentNullException if item == null.
  264. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Contains"]/*' />
  265. public bool Contains(T item) {
  266. int index = _head;
  267. int count = _size;
  268.  
  269. EqualityComparer<T> c = EqualityComparer<T>.Default;
  270. while (count-- > 0) {
  271. if (((Object) item) == null) {
  272. if (((Object) _array[index]) == null)
  273. return true;
  274. }
  275. else if (_array[index] != null && c.Equals(_array[index], item)) {
  276. return true;
  277. }
  278. index = (index + 1) % _array.Length;
  279. }
  280.  
  281. return false;
  282. }
  283.  
  284. internal T GetElement(int i)
  285. {
  286. return _array[(_head + i) % _array.Length];
  287. }
  288.  
  289. // Iterates over the objects in the queue, returning an array of the
  290. // objects in the Queue, or an empty array if the queue is empty.
  291. // The order of elements in the array is first in to last in, the same
  292. // order produced by successive calls to Dequeue.
  293. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.ToArray"]/*' />
  294. public T[] ToArray()
  295. {
  296. T[] arr = new T[_size];
  297. if (_size==0)
  298. return arr;
  299.  
  300. if (_head < _tail) {
  301. Array.Copy(_array, _head, arr, 0, _size);
  302. } else {
  303. Array.Copy(_array, _head, arr, 0, _array.Length - _head);
  304. Array.Copy(_array, 0, arr, _array.Length - _head, _tail);
  305. }
  306.  
  307. return arr;
  308. }
  309.  
  310.  
  311. // PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity
  312. // must be >= _size.
  313. private void SetCapacity(int capacity) {
  314. T[] newarray = new T[capacity];
  315. if (_size > 0) {
  316. if (_head < _tail) {
  317. Array.Copy(_array, _head, newarray, 0, _size);
  318. } else {
  319. Array.Copy(_array, _head, newarray, 0, _array.Length - _head);
  320. Array.Copy(_array, 0, newarray, _array.Length - _head, _tail);
  321. }
  322. }
  323.  
  324. _array = newarray;
  325. _head = 0;
  326. _tail = (_size == capacity) ? 0 : _size;
  327. _version++;
  328. }
  329.  
  330. public void TrimExcess() {
  331. int threshold = (int)(((double)_array.Length) * 0.9);
  332. if( _size < threshold ) {
  333. SetCapacity(_size);
  334. }
  335. }
  336.  
  337. // Implements an enumerator for a Queue. The enumerator uses the
  338. // internal version number of the list to ensure that no modifications are
  339. // made to the list while an enumeration is in progress.
  340. /// <include file='doc\Queue.uex' path='docs/doc[@for="QueueEnumerator"]/*' />
  341. #if !SILVERLIGHT
  342. [Serializable()]
  343. #endif
  344. [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
  345. public struct Enumerator : IEnumerator<T>,
  346. System.Collections.IEnumerator
  347. {
  348. private Queue<T> _q;
  349. private int _index; // -1 = not started, -2 = ended/disposed
  350. private int _version;
  351. private T _currentElement;
  352.  
  353. internal Enumerator(Queue<T> q) {
  354. _q = q;
  355. _version = _q._version;
  356. _index = -1;
  357. _currentElement = default(T);
  358. }
  359.  
  360. /// <include file='doc\Queue.uex' path='docs/doc[@for="QueueEnumerator.Dispose"]/*' />
  361. public void Dispose()
  362. {
  363. _index = -2;
  364. _currentElement = default(T);
  365. }
  366.  
  367. /// <include file='doc\Queue.uex' path='docs/doc[@for="QueueEnumerator.MoveNext"]/*' />
  368. public bool MoveNext() {
  369. if (_version != _q._version) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
  370.  
  371. if (_index == -2)
  372. return false;
  373.  
  374. _index++;
  375.  
  376. if (_index == _q._size) {
  377. _index = -2;
  378. _currentElement = default(T);
  379. return false;
  380. }
  381.  
  382. _currentElement = _q.GetElement(_index);
  383. return true;
  384. }
  385.  
  386. /// <include file='doc\Queue.uex' path='docs/doc[@for="QueueEnumerator.Current"]/*' />
  387. public T Current {
  388. get {
  389. if (_index < 0)
  390. {
  391. if (_index == -1)
  392. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
  393. else
  394. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
  395. }
  396. return _currentElement;
  397. }
  398. }
  399.  
  400. Object System.Collections.IEnumerator.Current {
  401. get {
  402. if (_index < 0)
  403. {
  404. if (_index == -1)
  405. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
  406. else
  407. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
  408. }
  409. return _currentElement;
  410. }
  411. }
  412.  
  413. void System.Collections.IEnumerator.Reset() {
  414. if (_version != _q._version) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
  415. _index = -1;
  416. _currentElement = default(T);
  417. }
  418. }
  419. }
  420. }
  421.  
  422. // ==++==
  423. //
  424. // Copyright (c) Microsoft Corporation. All rights reserved.
  425. //
  426. // ==--==
  427. /*=============================================================================
  428. **
  429. ** Class: Stack
  430. **
  431. ** Purpose: An array implementation of a generic stack.
  432. **
  433. ** Date: January 28, 2003
  434. **
  435. =============================================================================*/
  436. namespace System.Collections.Generic {
  437. using System;
  438. using System.Diagnostics;
  439. using System.Diagnostics.CodeAnalysis;
  440. using System.Security.Permissions;
  441.  
  442. // A simple stack of objects. Internally it is implemented as an array,
  443. // so Push can be O(n). Pop is O(1).
  444.  
  445. [DebuggerTypeProxy(typeof(System_StackDebugView<>))]
  446. [DebuggerDisplay("Count = {Count}")]
  447. #if !SILVERLIGHT
  448. [Serializable()]
  449. #endif
  450. [System.Runtime.InteropServices.ComVisible(false)]
  451. public class Stack<T> : IEnumerable<T>,
  452. System.Collections.ICollection,
  453. IReadOnlyCollection<T> {
  454. private T[] _array; // Storage for stack elements
  455. private int _size; // Number of items in the stack.
  456. private int _version; // Used to keep enumerator in [....] w/ collection.
  457. #if !SILVERLIGHT
  458. [NonSerialized]
  459. #endif
  460. private Object _syncRoot;
  461.  
  462. private const int _defaultCapacity = 4;
  463. static T[] _emptyArray = new T[0];
  464.  
  465. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Stack"]/*' />
  466. public Stack() {
  467. _array = _emptyArray;
  468. _size = 0;
  469. _version = 0;
  470. }
  471.  
  472. // Create a stack with a specific initial capacity. The initial capacity
  473. // must be a non-negative number.
  474. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Stack1"]/*' />
  475. public Stack(int capacity) {
  476. if (capacity < 0)
  477. ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNumRequired);
  478. _array = new T[capacity];
  479. _size = 0;
  480. _version = 0;
  481. }
  482.  
  483. // Fills a Stack with the contents of a particular collection. The items are
  484. // pushed onto the stack in the same order they are read by the enumerator.
  485. //
  486. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Stack2"]/*' />
  487. public Stack(IEnumerable<T> collection)
  488. {
  489. if (collection==null)
  490. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
  491.  
  492. ICollection<T> c = collection as ICollection<T>;
  493. if( c != null) {
  494. int count = c.Count;
  495. _array = new T[count];
  496. c.CopyTo(_array, 0);
  497. _size = count;
  498. }
  499. else {
  500. _size = 0;
  501. _array = new T[_defaultCapacity];
  502.  
  503. using(IEnumerator<T> en = collection.GetEnumerator()) {
  504. while(en.MoveNext()) {
  505. Push(en.Current);
  506. }
  507. }
  508. }
  509. }
  510.  
  511. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Count"]/*' />
  512. public int Count {
  513. get { return _size; }
  514. }
  515.  
  516. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.IsSynchronized"]/*' />
  517. bool System.Collections.ICollection.IsSynchronized {
  518. get { return false; }
  519. }
  520.  
  521. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.SyncRoot"]/*' />
  522. Object System.Collections.ICollection.SyncRoot {
  523. get {
  524. if( _syncRoot == null) {
  525. System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
  526. }
  527. return _syncRoot;
  528. }
  529. }
  530.  
  531. // Removes all Objects from the Stack.
  532. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Clear"]/*' />
  533. public void Clear() {
  534. Array.Clear(_array, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
  535. _size = 0;
  536. _version++;
  537. }
  538.  
  539. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Contains"]/*' />
  540. public bool Contains(T item) {
  541. int count = _size;
  542.  
  543. EqualityComparer<T> c = EqualityComparer<T>.Default;
  544. while (count-- > 0) {
  545. if (((Object) item) == null) {
  546. if (((Object) _array[count]) == null)
  547. return true;
  548. }
  549. else if (_array[count] != null && c.Equals(_array[count], item) ) {
  550. return true;
  551. }
  552. }
  553. return false;
  554. }
  555.  
  556. // Copies the stack into an array.
  557. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.CopyTo"]/*' />
  558. public void CopyTo(T[] array, int arrayIndex) {
  559. if (array==null) {
  560. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
  561. }
  562.  
  563. if (arrayIndex < 0 || arrayIndex > array.Length) {
  564. ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
  565. }
  566.  
  567. if (array.Length - arrayIndex < _size) {
  568. ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
  569. }
  570.  
  571. Array.Copy(_array, 0, array, arrayIndex, _size);
  572. Array.Reverse(array, arrayIndex, _size);
  573. }
  574.  
  575. void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) {
  576. if (array==null) {
  577. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
  578. }
  579.  
  580. if (array.Rank != 1) {
  581. ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
  582. }
  583.  
  584. if( array.GetLowerBound(0) != 0 ) {
  585. ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
  586. }
  587.  
  588. if (arrayIndex < 0 || arrayIndex > array.Length) {
  589. ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
  590. }
  591.  
  592. if (array.Length - arrayIndex < _size) {
  593. ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
  594. }
  595.  
  596. try {
  597. Array.Copy(_array, 0, array, arrayIndex, _size);
  598. Array.Reverse(array, arrayIndex, _size);
  599. }
  600. catch(ArrayTypeMismatchException){
  601. ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
  602. }
  603. }
  604.  
  605. // Returns an IEnumerator for this Stack.
  606. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.GetEnumerator"]/*' />
  607. public Enumerator GetEnumerator() {
  608. return new Enumerator(this);
  609. }
  610.  
  611. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.IEnumerable.GetEnumerator"]/*' />
  612. /// <internalonly/>
  613. IEnumerator<T> IEnumerable<T>.GetEnumerator() {
  614. return new Enumerator(this);
  615. }
  616.  
  617. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
  618. return new Enumerator(this);
  619. }
  620.  
  621. public void TrimExcess() {
  622. int threshold = (int)(((double)_array.Length) * 0.9);
  623. if( _size < threshold ) {
  624. T[] newarray = new T[_size];
  625. Array.Copy(_array, 0, newarray, 0, _size);
  626. _array = newarray;
  627. _version++;
  628. }
  629. }
  630.  
  631. // Returns the top object on the stack without removing it. If the stack
  632. // is empty, Peek throws an InvalidOperationException.
  633. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Peek"]/*' />
  634. public T Peek() {
  635. if (_size==0)
  636. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);
  637. return _array[_size-1];
  638. }
  639.  
  640. // Pops an item from the top of the stack. If the stack is empty, Pop
  641. // throws an InvalidOperationException.
  642. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Pop"]/*' />
  643. public T Pop() {
  644. if (_size == 0)
  645. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);
  646. _version++;
  647. T item = _array[--_size];
  648. _array[_size] = default(T); // Free memory quicker.
  649. return item;
  650. }
  651.  
  652. // Pushes an item to the top of the stack.
  653. //
  654. /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Push"]/*' />
  655. public void Push(T item) {
  656. if (_size == _array.Length) {
  657. T[] newArray = new T[(_array.Length == 0) ? _defaultCapacity : 2*_array.Length];
  658. Array.Copy(_array, 0, newArray, 0, _size);
  659. _array = newArray;
  660. }
  661. _array[_size++] = item;
  662. _version++;
  663. }
  664.  
  665. // Copies the Stack to an array, in the same order Pop would return the items.
  666. public T[] ToArray()
  667. {
  668. T[] objArray = new T[_size];
  669. int i = 0;
  670. while(i < _size) {
  671. objArray[i] = _array[_size-i-1];
  672. i++;
  673. }
  674. return objArray;
  675. }
  676.  
  677. /// <include file='doc\Stack.uex' path='docs/doc[@for="StackEnumerator"]/*' />
  678. #if !SILVERLIGHT
  679. [Serializable()]
  680. #endif
  681. [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
  682. public struct Enumerator : IEnumerator<T>,
  683. System.Collections.IEnumerator
  684. {
  685. private Stack<T> _stack;
  686. private int _index;
  687. private int _version;
  688. private T currentElement;
  689.  
  690. internal Enumerator(Stack<T> stack) {
  691. _stack = stack;
  692. _version = _stack._version;
  693. _index = -2;
  694. currentElement = default(T);
  695. }
  696.  
  697. /// <include file='doc\Stack.uex' path='docs/doc[@for="StackEnumerator.Dispose"]/*' />
  698. public void Dispose()
  699. {
  700. _index = -1;
  701. }
  702.  
  703. /// <include file='doc\Stack.uex' path='docs/doc[@for="StackEnumerator.MoveNext"]/*' />
  704. public bool MoveNext() {
  705. bool retval;
  706. if (_version != _stack._version) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
  707. if (_index == -2) { // First call to enumerator.
  708. _index = _stack._size-1;
  709. retval = ( _index >= 0);
  710. if (retval)
  711. currentElement = _stack._array[_index];
  712. return retval;
  713. }
  714. if (_index == -1) { // End of enumeration.
  715. return false;
  716. }
  717.  
  718. retval = (--_index >= 0);
  719. if (retval)
  720. currentElement = _stack._array[_index];
  721. else
  722. currentElement = default(T);
  723. return retval;
  724. }
  725.  
  726. /// <include file='doc\Stack.uex' path='docs/doc[@for="StackEnumerator.Current"]/*' />
  727. public T Current {
  728. get {
  729. if (_index == -2) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
  730. if (_index == -1) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
  731. return currentElement;
  732. }
  733. }
  734.  
  735. Object System.Collections.IEnumerator.Current {
  736. get {
  737. if (_index == -2) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
  738. if (_index == -1) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
  739. return currentElement;
  740. }
  741. }
  742.  
  743. void System.Collections.IEnumerator.Reset() {
  744. if (_version != _stack._version) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
  745. _index = -2;
  746. currentElement = default(T);
  747. }
  748. }
  749. }
  750. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement