5 // Joe Shaw (joe@ximian.com)
6 // Martin Baulig (martin@gnome.org)
7 // Dietmar Maurer (dietmar@ximian.com)
8 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
10 // (C) 2001-2003 Ximian, Inc. http://www.ximian.com
11 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
37 using System.Collections.Generic;
38 using System.Collections.ObjectModel;
39 using System.Runtime.ConstrainedExecution;
45 // FIXME: We are doing way to many double/triple exception checks for the overloaded functions"
46 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
54 * These methods are used to implement the implicit generic interfaces
55 * implemented by arrays in NET 2.0.
56 * Only make those methods generic which really need it, to avoid
57 * creating useless instantiations.
59 internal int InternalArray__ICollection_get_Count ()
64 internal bool InternalArray__ICollection_get_IsReadOnly ()
69 internal IEnumerator<T> InternalArray__IEnumerable_GetEnumerator<T> ()
71 return new InternalEnumerator<T> (this);
74 internal void InternalArray__ICollection_Clear ()
76 throw new NotSupportedException ("Collection is read-only");
79 internal void InternalArray__ICollection_Add<T> (T item)
81 throw new NotSupportedException ("Collection is read-only");
84 internal bool InternalArray__ICollection_Remove<T> (T item)
86 throw new NotSupportedException ("Collection is read-only");
89 internal bool InternalArray__ICollection_Contains<T> (T item)
92 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
94 int length = this.Length;
95 for (int i = 0; i < length; i++) {
97 GetGenericValueImpl (i, out value);
105 if (item.Equals (value))
112 internal void InternalArray__ICollection_CopyTo<T> (T[] array, int index)
115 throw new ArgumentNullException ("array");
117 // The order of these exception checks may look strange,
118 // but that's how the microsoft runtime does it.
120 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
121 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
122 throw new ArgumentException ("Destination array was not long " +
123 "enough. Check destIndex and length, and the array's " +
126 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
128 throw new ArgumentOutOfRangeException (
129 "index", Locale.GetText ("Value has to be >= 0."));
131 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
134 internal void InternalArray__Insert<T> (int index, T item)
136 throw new NotSupportedException ("Collection is read-only");
139 internal void InternalArray__RemoveAt (int index)
141 throw new NotSupportedException ("Collection is read-only");
144 internal int InternalArray__IndexOf<T> (T item)
147 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
149 int length = this.Length;
150 for (int i = 0; i < length; i++) {
152 GetGenericValueImpl (i, out value);
155 return i + this.GetLowerBound (0);
158 return this.GetLowerBound (0) - 1;
162 if (value.Equals (item))
163 // array index may not be zero-based.
165 return i + this.GetLowerBound (0);
169 // lower bound may be MinValue
170 return this.GetLowerBound (0) - 1;
174 internal T InternalArray__get_Item<T> (int index)
176 if (unchecked ((uint) index) >= unchecked ((uint) Length))
177 throw new ArgumentOutOfRangeException ("index");
180 GetGenericValueImpl (index, out value);
184 internal void InternalArray__set_Item<T> (int index, T item)
186 if (unchecked ((uint) index) >= unchecked ((uint) Length))
187 throw new ArgumentOutOfRangeException ("index");
189 object[] oarray = this as object [];
190 if (oarray != null) {
191 oarray [index] = (object)item;
194 SetGenericValueImpl (index, ref item);
197 // CAUTION! No bounds checking!
198 [MethodImplAttribute (MethodImplOptions.InternalCall)]
199 internal extern void GetGenericValueImpl<T> (int pos, out T value);
201 // CAUTION! No bounds checking!
202 [MethodImplAttribute (MethodImplOptions.InternalCall)]
203 internal extern void SetGenericValueImpl<T> (int pos, ref T value);
205 internal struct InternalEnumerator<T> : IEnumerator<T>
207 const int NOT_STARTED = -2;
209 // this MUST be -1, because we depend on it in move next.
210 // we just decr the size, so, 0 - 1 == FINISHED
211 const int FINISHED = -1;
216 internal InternalEnumerator (Array array)
222 public void Dispose ()
227 public bool MoveNext ()
229 if (idx == NOT_STARTED)
232 return idx != FINISHED && -- idx != FINISHED;
237 if (idx == NOT_STARTED)
238 throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
240 throw new InvalidOperationException ("Enumeration already finished");
242 return array.InternalArray__get_Item<T> (array.Length - 1 - idx);
246 void IEnumerator.Reset ()
251 object IEnumerator.Current {
260 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
262 int length = this.GetLength (0);
264 for (int i = 1; i < this.Rank; i++) {
265 length *= this.GetLength (i);
272 public long LongLength {
273 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
274 get { return Length; }
278 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
280 return this.GetRank ();
285 object IList.this [int index] {
287 if (unchecked ((uint) index) >= unchecked ((uint) Length))
288 throw new IndexOutOfRangeException ("index");
289 return GetValueImpl (index);
292 if (unchecked ((uint) index) >= unchecked ((uint) Length))
293 throw new IndexOutOfRangeException ("index");
294 SetValueImpl (value, index);
298 int IList.Add (object value)
300 throw new NotSupportedException ();
305 Array.Clear (this, this.GetLowerBound (0), this.Length);
308 bool IList.Contains (object value)
311 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
313 int length = this.Length;
314 for (int i = 0; i < length; i++) {
315 if (Object.Equals (this.GetValueImpl (i), value))
321 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
322 int IList.IndexOf (object value)
325 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
327 int length = this.Length;
328 for (int i = 0; i < length; i++) {
329 if (Object.Equals (this.GetValueImpl (i), value))
330 // array index may not be zero-based.
332 return i + this.GetLowerBound (0);
336 // lower bound may be MinValue
337 return this.GetLowerBound (0) - 1;
341 void IList.Insert (int index, object value)
343 throw new NotSupportedException ();
346 void IList.Remove (object value)
348 throw new NotSupportedException ();
351 void IList.RemoveAt (int index)
353 throw new NotSupportedException ();
356 // InternalCall Methods
357 [MethodImplAttribute (MethodImplOptions.InternalCall)]
358 extern int GetRank ();
360 [MethodImplAttribute (MethodImplOptions.InternalCall)]
361 public extern int GetLength (int dimension);
364 public long GetLongLength (int dimension)
366 return GetLength (dimension);
369 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
370 [MethodImplAttribute (MethodImplOptions.InternalCall)]
371 public extern int GetLowerBound (int dimension);
373 [MethodImplAttribute (MethodImplOptions.InternalCall)]
374 public extern object GetValue (params int[] indices);
376 [MethodImplAttribute (MethodImplOptions.InternalCall)]
377 public extern void SetValue (object value, params int[] indices);
379 // CAUTION! No bounds checking!
380 [MethodImplAttribute (MethodImplOptions.InternalCall)]
381 internal extern object GetValueImpl (int pos);
383 // CAUTION! No bounds checking!
384 [MethodImplAttribute (MethodImplOptions.InternalCall)]
385 internal extern void SetValueImpl (object value, int pos);
387 [MethodImplAttribute (MethodImplOptions.InternalCall)]
388 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
390 [MethodImplAttribute (MethodImplOptions.InternalCall)]
391 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
394 int ICollection.Count {
400 public bool IsSynchronized {
406 public object SyncRoot {
412 public bool IsFixedSize {
418 public bool IsReadOnly {
424 public IEnumerator GetEnumerator ()
426 return new SimpleEnumerator (this);
429 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
430 public int GetUpperBound (int dimension)
432 return GetLowerBound (dimension) + GetLength (dimension) - 1;
435 public object GetValue (int index)
438 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
439 if (index < GetLowerBound (0) || index > GetUpperBound (0))
440 throw new IndexOutOfRangeException (Locale.GetText (
441 "Index has to be between upper and lower bound of the array."));
443 return GetValueImpl (index - GetLowerBound (0));
446 public object GetValue (int index1, int index2)
448 int[] ind = {index1, index2};
449 return GetValue (ind);
452 public object GetValue (int index1, int index2, int index3)
454 int[] ind = {index1, index2, index3};
455 return GetValue (ind);
459 public object GetValue (long index)
461 if (index < 0 || index > Int32.MaxValue)
462 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
463 "Value must be >= 0 and <= Int32.MaxValue."));
465 return GetValue ((int) index);
469 public object GetValue (long index1, long index2)
471 if (index1 < 0 || index1 > Int32.MaxValue)
472 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
473 "Value must be >= 0 and <= Int32.MaxValue."));
475 if (index2 < 0 || index2 > Int32.MaxValue)
476 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
477 "Value must be >= 0 and <= Int32.MaxValue."));
479 return GetValue ((int) index1, (int) index2);
483 public object GetValue (long index1, long index2, long index3)
485 if (index1 < 0 || index1 > Int32.MaxValue)
486 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
487 "Value must be >= 0 and <= Int32.MaxValue."));
489 if (index2 < 0 || index2 > Int32.MaxValue)
490 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
491 "Value must be >= 0 and <= Int32.MaxValue."));
493 if (index3 < 0 || index3 > Int32.MaxValue)
494 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
495 "Value must be >= 0 and <= Int32.MaxValue."));
497 return GetValue ((int) index1, (int) index2, (int) index3);
501 public void SetValue (object value, long index)
503 if (index < 0 || index > Int32.MaxValue)
504 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
505 "Value must be >= 0 and <= Int32.MaxValue."));
507 SetValue (value, (int) index);
511 public void SetValue (object value, long index1, long index2)
513 if (index1 < 0 || index1 > Int32.MaxValue)
514 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
515 "Value must be >= 0 and <= Int32.MaxValue."));
517 if (index2 < 0 || index2 > Int32.MaxValue)
518 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
519 "Value must be >= 0 and <= Int32.MaxValue."));
521 int[] ind = {(int) index1, (int) index2};
522 SetValue (value, ind);
526 public void SetValue (object value, long index1, long index2, long index3)
528 if (index1 < 0 || index1 > Int32.MaxValue)
529 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
530 "Value must be >= 0 and <= Int32.MaxValue."));
532 if (index2 < 0 || index2 > Int32.MaxValue)
533 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
534 "Value must be >= 0 and <= Int32.MaxValue."));
536 if (index3 < 0 || index3 > Int32.MaxValue)
537 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
538 "Value must be >= 0 and <= Int32.MaxValue."));
540 int[] ind = {(int) index1, (int) index2, (int) index3};
541 SetValue (value, ind);
544 public void SetValue (object value, int index)
547 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
548 if (index < GetLowerBound (0) || index > GetUpperBound (0))
549 throw new IndexOutOfRangeException (Locale.GetText (
550 "Index has to be >= lower bound and <= upper bound of the array."));
552 SetValueImpl (value, index - GetLowerBound (0));
555 public void SetValue (object value, int index1, int index2)
557 int[] ind = {index1, index2};
558 SetValue (value, ind);
561 public void SetValue (object value, int index1, int index2, int index3)
563 int[] ind = {index1, index2, index3};
564 SetValue (value, ind);
567 public static Array CreateInstance (Type elementType, int length)
569 int[] lengths = {length};
571 return CreateInstance (elementType, lengths);
574 public static Array CreateInstance (Type elementType, int length1, int length2)
576 int[] lengths = {length1, length2};
578 return CreateInstance (elementType, lengths);
581 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
583 int[] lengths = {length1, length2, length3};
585 return CreateInstance (elementType, lengths);
588 public static Array CreateInstance (Type elementType, params int[] lengths)
590 if (elementType == null)
591 throw new ArgumentNullException ("elementType");
593 throw new ArgumentNullException ("lengths");
595 if (lengths.Length > 255)
596 throw new TypeLoadException ();
600 elementType = elementType.UnderlyingSystemType;
601 if (!elementType.IsSystemType)
602 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
604 return CreateInstanceImpl (elementType, lengths, bounds);
607 public static Array CreateInstance (Type elementType, int[] lengths, int [] lowerBounds)
609 if (elementType == null)
610 throw new ArgumentNullException ("elementType");
612 throw new ArgumentNullException ("lengths");
613 if (lowerBounds == null)
614 throw new ArgumentNullException ("lowerBounds");
616 elementType = elementType.UnderlyingSystemType;
617 if (!elementType.IsSystemType)
618 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
620 if (lengths.Length < 1)
621 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
623 if (lengths.Length != lowerBounds.Length)
624 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
626 for (int j = 0; j < lowerBounds.Length; j ++) {
628 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
629 "Each value has to be >= 0."));
630 if ((long)lowerBounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
631 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
632 "Length + bound must not exceed Int32.MaxValue."));
635 if (lengths.Length > 255)
636 throw new TypeLoadException ();
638 return CreateInstanceImpl (elementType, lengths, lowerBounds);
641 static int [] GetIntArray (long [] values)
643 int len = values.Length;
644 int [] ints = new int [len];
645 for (int i = 0; i < len; i++) {
646 long current = values [i];
647 if (current < 0 || current > (long) Int32.MaxValue)
648 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
649 "Each value has to be >= 0 and <= Int32.MaxValue."));
651 ints [i] = (int) current;
656 public static Array CreateInstance (Type elementType, params long [] lengths)
659 throw new ArgumentNullException ("lengths");
660 return CreateInstance (elementType, GetIntArray (lengths));
664 public object GetValue (params long [] indices)
667 throw new ArgumentNullException ("indices");
668 return GetValue (GetIntArray (indices));
672 public void SetValue (object value, params long [] indices)
675 throw new ArgumentNullException ("indices");
676 SetValue (value, GetIntArray (indices));
679 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
680 public static int BinarySearch (Array array, object value)
683 throw new ArgumentNullException ("array");
689 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
691 if (array.Length == 0)
694 if (!(value is IComparable))
695 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
697 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
700 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
701 public static int BinarySearch (Array array, object value, IComparer comparer)
704 throw new ArgumentNullException ("array");
707 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
709 if (array.Length == 0)
712 if ((comparer == null) && (value != null) && !(value is IComparable))
713 throw new ArgumentException (Locale.GetText (
714 "comparer is null and value does not support IComparable."));
716 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
719 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
720 public static int BinarySearch (Array array, int index, int length, object value)
723 throw new ArgumentNullException ("array");
726 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
728 if (index < array.GetLowerBound (0))
729 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
730 "index is less than the lower bound of array."));
732 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
733 "Value has to be >= 0."));
734 // re-ordered to avoid possible integer overflow
735 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
736 throw new ArgumentException (Locale.GetText (
737 "index and length do not specify a valid range in array."));
739 if (array.Length == 0)
742 if ((value != null) && (!(value is IComparable)))
743 throw new ArgumentException (Locale.GetText (
744 "value does not support IComparable"));
746 return DoBinarySearch (array, index, length, value, null);
749 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
750 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
753 throw new ArgumentNullException ("array");
756 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
758 if (index < array.GetLowerBound (0))
759 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
760 "index is less than the lower bound of array."));
762 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
763 "Value has to be >= 0."));
764 // re-ordered to avoid possible integer overflow
765 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
766 throw new ArgumentException (Locale.GetText (
767 "index and length do not specify a valid range in array."));
769 if (array.Length == 0)
772 if ((comparer == null) && (value != null) && !(value is IComparable))
773 throw new ArgumentException (Locale.GetText (
774 "comparer is null and value does not support IComparable."));
776 return DoBinarySearch (array, index, length, value, comparer);
779 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
781 // cache this in case we need it
782 if (comparer == null)
783 comparer = Comparer.Default;
786 // Comment from Tum (tum@veridicus.com):
787 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
788 int iMax = index + length - 1;
791 while (iMin <= iMax) {
792 // Be careful with overflow
793 // http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
794 int iMid = iMin + ((iMax - iMin) / 2);
795 object elt = array.GetValueImpl (iMid);
797 iCmp = comparer.Compare (elt, value);
804 iMin = iMid + 1; // compensate for the rounding down
807 catch (Exception e) {
808 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
814 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
815 public static void Clear (Array array, int index, int length)
818 throw new ArgumentNullException ("array");
820 throw new ArgumentOutOfRangeException ("length < 0");
822 int low = array.GetLowerBound (0);
824 throw new IndexOutOfRangeException ("index < lower bound");
827 // re-ordered to avoid possible integer overflow
828 if (index > array.Length - length)
829 throw new IndexOutOfRangeException ("index + length > size");
831 ClearInternal (array, index, length);
834 [MethodImplAttribute (MethodImplOptions.InternalCall)]
835 static extern void ClearInternal (Array a, int index, int count);
837 [MethodImplAttribute (MethodImplOptions.InternalCall)]
838 public extern object Clone ();
840 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
841 public static void Copy (Array sourceArray, Array destinationArray, int length)
843 // need these checks here because we are going to use
844 // GetLowerBound() on source and dest.
845 if (sourceArray == null)
846 throw new ArgumentNullException ("sourceArray");
848 if (destinationArray == null)
849 throw new ArgumentNullException ("destinationArray");
851 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
852 destinationArray.GetLowerBound (0), length);
855 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
856 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
858 if (sourceArray == null)
859 throw new ArgumentNullException ("sourceArray");
861 if (destinationArray == null)
862 throw new ArgumentNullException ("destinationArray");
865 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
866 "Value has to be >= 0."));;
869 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
870 "Value has to be >= 0."));;
872 if (destinationIndex < 0)
873 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
874 "Value has to be >= 0."));;
876 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
879 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
880 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
882 // re-ordered to avoid possible integer overflow
883 if (source_pos > sourceArray.Length - length)
884 throw new ArgumentException ("length");
886 if (dest_pos > destinationArray.Length - length) {
887 string msg = "Destination array was not long enough. Check " +
888 "destIndex and length, and the array's lower bounds";
889 throw new ArgumentException (msg, string.Empty);
892 if (sourceArray.Rank != destinationArray.Rank)
893 throw new RankException (Locale.GetText ("Arrays must be of same size."));
895 Type src_type = sourceArray.GetType ().GetElementType ();
896 Type dst_type = destinationArray.GetType ().GetElementType ();
898 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
899 for (int i = 0; i < length; i++) {
900 Object srcval = sourceArray.GetValueImpl (source_pos + i);
903 destinationArray.SetValueImpl (srcval, dest_pos + i);
905 if (src_type.Equals (typeof (Object)))
906 throw new InvalidCastException ();
908 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
909 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
914 for (int i = length - 1; i >= 0; i--) {
915 Object srcval = sourceArray.GetValueImpl (source_pos + i);
918 destinationArray.SetValueImpl (srcval, dest_pos + i);
920 if (src_type.Equals (typeof (Object)))
921 throw new InvalidCastException ();
923 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
924 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
930 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
931 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
932 long destinationIndex, long length)
934 if (sourceArray == null)
935 throw new ArgumentNullException ("sourceArray");
937 if (destinationArray == null)
938 throw new ArgumentNullException ("destinationArray");
940 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
941 throw new ArgumentOutOfRangeException ("sourceIndex",
942 Locale.GetText ("Must be in the Int32 range."));
944 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
945 throw new ArgumentOutOfRangeException ("destinationIndex",
946 Locale.GetText ("Must be in the Int32 range."));
948 if (length < 0 || length > Int32.MaxValue)
949 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
950 "Value must be >= 0 and <= Int32.MaxValue."));
952 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
955 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
956 public static void Copy (Array sourceArray, Array destinationArray, long length)
958 if (length < 0 || length > Int32.MaxValue)
959 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
960 "Value must be >= 0 and <= Int32.MaxValue."));
962 Copy (sourceArray, destinationArray, (int) length);
965 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
966 public static int IndexOf (Array array, object value)
969 throw new ArgumentNullException ("array");
971 return IndexOf (array, value, 0, array.Length);
974 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
975 public static int IndexOf (Array array, object value, int startIndex)
978 throw new ArgumentNullException ("array");
980 return IndexOf (array, value, startIndex, array.Length - startIndex);
983 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
984 public static int IndexOf (Array array, object value, int startIndex, int count)
987 throw new ArgumentNullException ("array");
990 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
992 // re-ordered to avoid possible integer overflow
993 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
994 throw new ArgumentOutOfRangeException ();
996 int max = startIndex + count;
997 for (int i = startIndex; i < max; i++) {
998 if (Object.Equals (array.GetValueImpl (i), value))
1002 return array.GetLowerBound (0) - 1;
1005 public void Initialize()
1007 //FIXME: We would like to find a compiler that uses
1008 // this method. It looks like this method do nothing
1009 // in C# so no exception is trown by the moment.
1012 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1013 public static int LastIndexOf (Array array, object value)
1016 throw new ArgumentNullException ("array");
1018 if (array.Length == 0)
1019 return array.GetLowerBound (0) - 1;
1020 return LastIndexOf (array, value, array.Length - 1);
1023 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1024 public static int LastIndexOf (Array array, object value, int startIndex)
1027 throw new ArgumentNullException ("array");
1029 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
1032 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1033 public static int LastIndexOf (Array array, object value, int startIndex, int count)
1036 throw new ArgumentNullException ("array");
1039 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1041 int lb = array.GetLowerBound (0);
1042 // Empty arrays do not throw ArgumentOutOfRangeException
1043 if (array.Length == 0)
1046 if (count < 0 || startIndex < lb ||
1047 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < lb)
1048 throw new ArgumentOutOfRangeException ();
1050 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1051 if (Object.Equals (array.GetValueImpl (i), value))
1058 /* delegate used to swap array elements */
1059 delegate void Swapper (int i, int j);
1061 static Swapper get_swapper (Array array)
1064 return new Swapper (array.int_swapper);
1065 if (array is double[])
1066 return new Swapper (array.double_swapper);
1067 if (array is object[]) {
1068 return new Swapper (array.obj_swapper);
1070 return new Swapper (array.slow_swapper);
1073 static Swapper get_swapper<T> (T [] array)
1076 return new Swapper (array.int_swapper);
1077 if (array is double[])
1078 return new Swapper (array.double_swapper);
1080 // gmcs refuses to compile this
1081 //return new Swapper (array.generic_swapper<T>);
1082 return new Swapper (array.slow_swapper);
1085 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1086 public static void Reverse (Array array)
1089 throw new ArgumentNullException ("array");
1091 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
1094 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1095 public static void Reverse (Array array, int index, int length)
1098 throw new ArgumentNullException ("array");
1101 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1103 if (index < array.GetLowerBound (0) || length < 0)
1104 throw new ArgumentOutOfRangeException ();
1106 // re-ordered to avoid possible integer overflow
1107 if (index > array.GetUpperBound (0) + 1 - length)
1108 throw new ArgumentException ();
1110 int end = index + length - 1;
1111 object[] oarray = array as object[];
1112 if (oarray != null) {
1113 while (index < end) {
1114 object tmp = oarray [index];
1115 oarray [index] = oarray [end];
1122 int[] iarray = array as int[];
1123 if (iarray != null) {
1124 while (index < end) {
1125 int tmp = iarray [index];
1126 iarray [index] = iarray [end];
1133 double[] darray = array as double[];
1134 if (darray != null) {
1135 while (index < end) {
1136 double tmp = darray [index];
1137 darray [index] = darray [end];
1145 Swapper swapper = get_swapper (array);
1146 while (index < end) {
1147 swapper (index, end);
1153 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1154 public static void Sort (Array array)
1156 Sort (array, (IComparer)null);
1159 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1160 public static void Sort (Array keys, Array items)
1162 Sort (keys, items, (IComparer)null);
1165 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1166 public static void Sort (Array array, IComparer comparer)
1169 throw new ArgumentNullException ("array");
1172 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1174 SortImpl (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1177 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1178 public static void Sort (Array array, int index, int length)
1180 Sort (array, index, length, (IComparer)null);
1183 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1184 public static void Sort (Array keys, Array items, IComparer comparer)
1186 if (items == null) {
1187 Sort (keys, comparer);
1192 throw new ArgumentNullException ("keys");
1194 if (keys.Rank > 1 || items.Rank > 1)
1195 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1197 SortImpl (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1200 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1201 public static void Sort (Array keys, Array items, int index, int length)
1203 Sort (keys, items, index, length, (IComparer)null);
1206 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1207 public static void Sort (Array array, int index, int length, IComparer comparer)
1210 throw new ArgumentNullException ("array");
1213 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1215 if (index < array.GetLowerBound (0))
1216 throw new ArgumentOutOfRangeException ("index");
1219 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1220 "Value has to be >= 0."));
1222 if (array.Length - (array.GetLowerBound (0) + index) < length)
1223 throw new ArgumentException ();
1225 SortImpl (array, null, index, length, comparer);
1228 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1229 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1231 if (items == null) {
1232 Sort (keys, index, length, comparer);
1237 throw new ArgumentNullException ("keys");
1239 if (keys.Rank > 1 || items.Rank > 1)
1240 throw new RankException ();
1242 if (keys.GetLowerBound (0) != items.GetLowerBound (0))
1243 throw new ArgumentException ();
1245 if (index < keys.GetLowerBound (0))
1246 throw new ArgumentOutOfRangeException ("index");
1249 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1250 "Value has to be >= 0."));
1252 if (keys.Length != items.Length || keys.Length - (index + keys.GetLowerBound (0)) < length)
1253 throw new ArgumentException ();
1255 SortImpl (keys, items, index, length, comparer);
1258 private static void SortImpl (Array keys, Array items, int index, int length, IComparer comparer)
1263 if (comparer == null) {
1264 Swapper iswapper = (items != null ? get_swapper (items) : null);
1265 if (keys is double[]) {
1266 combsort (keys as double[], index, length, iswapper);
1269 if (keys is int[]) {
1270 combsort (keys as int[], index, length, iswapper);
1273 if (keys is char[]) {
1274 combsort (keys as char[], index, length, iswapper);
1280 int high = index + length - 1;
1281 low = MoveNullKeysToFront (keys, items, low, high, comparer == null);
1286 qsort (keys, items, low, high, comparer);
1287 } catch (Exception e) {
1288 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1292 /* note, these are instance methods */
1293 void int_swapper (int i, int j) {
1294 int[] array = this as int[];
1295 int val = array [i];
1296 array [i] = array [j];
1300 void obj_swapper (int i, int j) {
1301 object[] array = this as object[];
1302 object val = array [i];
1303 array [i] = array [j];
1307 void slow_swapper (int i, int j) {
1308 object val = GetValueImpl (i);
1309 SetValueImpl (GetValue (j), i);
1310 SetValueImpl (val, j);
1313 void double_swapper (int i, int j) {
1314 double[] array = this as double[];
1315 double val = array [i];
1316 array [i] = array [j];
1320 static int new_gap (int gap)
1322 gap = (gap * 10) / 13;
1323 if (gap == 9 || gap == 10)
1330 /* we use combsort because it's fast enough and very small, since we have
1331 * several specialized versions here.
1333 static void combsort (double[] array, int start, int size, Swapper swap_items)
1337 gap = new_gap (gap);
1338 bool swapped = false;
1339 int end = start + size - gap;
1340 for (int i = start; i < end; i++) {
1342 if (array [i] > array [j]) {
1343 double val = array [i];
1344 array [i] = array [j];
1347 if (swap_items != null)
1351 if (gap == 1 && !swapped)
1356 static void combsort (int[] array, int start, int size, Swapper swap_items)
1360 gap = new_gap (gap);
1361 bool swapped = false;
1362 int end = start + size - gap;
1363 for (int i = start; i < end; i++) {
1365 if (array [i] > array [j]) {
1366 int val = array [i];
1367 array [i] = array [j];
1370 if (swap_items != null)
1374 if (gap == 1 && !swapped)
1379 static void combsort (char[] array, int start, int size, Swapper swap_items)
1383 gap = new_gap (gap);
1384 bool swapped = false;
1385 int end = start + size - gap;
1386 for (int i = start; i < end; i++) {
1388 if (array [i] > array [j]) {
1389 char val = array [i];
1390 array [i] = array [j];
1393 if (swap_items != null)
1397 if (gap == 1 && !swapped)
1402 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1407 // Be careful with overflows
1408 int mid = low + ((high - low) / 2);
1409 object keyPivot = keys.GetValueImpl (mid);
1410 IComparable cmpPivot = keyPivot as IComparable;
1413 // Move the walls in
1414 if (comparer != null) {
1415 while (low < high0 && comparer.Compare (keyPivot, keys.GetValueImpl (low)) > 0)
1417 while (high > low0 && comparer.Compare (keyPivot, keys.GetValueImpl (high)) < 0)
1420 while (low < high0 && cmpPivot.CompareTo (keys.GetValueImpl (low)) > 0)
1422 while (high > low0 && cmpPivot.CompareTo (keys.GetValueImpl (high)) < 0)
1427 swap (keys, items, low, high);
1435 qsort (keys, items, low0, high, comparer);
1437 qsort (keys, items, low, high0, comparer);
1440 private static int MoveNullKeysToFront (Array keys, Array items, int low, int high, bool ensureComparable)
1442 // find first nun-null key
1443 while (low < high && keys.GetValueImpl (low) == null)
1446 // move null keys to beginning of array,
1447 // ensure that non-null keys implement IComparable
1448 for (int i = low + 1; i <= high; i++) {
1449 object obj = keys.GetValueImpl (i);
1451 swap (keys, items, low, i);
1454 if (ensureComparable && !(obj is IComparable)) {
1455 string msg = Locale.GetText ("No IComparable interface found for type '{0}'.");
1456 throw new InvalidOperationException (String.Format (msg, obj.GetType ()));
1463 private static void swap (Array keys, Array items, int i, int j)
1465 object tmp = keys.GetValueImpl (i);
1466 keys.SetValueImpl (keys.GetValueImpl (j), i);
1467 keys.SetValueImpl (tmp, j);
1469 if (items != null) {
1470 tmp = items.GetValueImpl (i);
1471 items.SetValueImpl (items.GetValueImpl (j), i);
1472 items.SetValueImpl (tmp, j);
1476 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1477 public static void Sort<T> (T [] array)
1479 Sort<T> (array, (IComparer<T>)null);
1482 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1483 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items)
1485 Sort<TKey, TValue> (keys, items, (IComparer<TKey>)null);
1488 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1489 public static void Sort<T> (T [] array, IComparer<T> comparer)
1492 throw new ArgumentNullException ("array");
1494 SortImpl<T, T> (array, null, 0, array.Length, comparer);
1497 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1498 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, IComparer<TKey> comparer)
1500 if (items == null) {
1501 Sort<TKey> (keys, comparer);
1506 throw new ArgumentNullException ("keys");
1508 if (keys.Length != items.Length)
1509 throw new ArgumentException ("Length of keys and items does not match.");
1511 SortImpl<TKey, TValue> (keys, items, 0, keys.Length, comparer);
1514 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1515 public static void Sort<T> (T [] array, int index, int length)
1517 Sort<T> (array, index, length, (IComparer<T>)null);
1520 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1521 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length)
1523 Sort<TKey, TValue> (keys, items, index, length, (IComparer<TKey>)null);
1526 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1527 public static void Sort<T> (T [] array, int index, int length, IComparer<T> comparer)
1530 throw new ArgumentNullException ("array");
1533 throw new ArgumentOutOfRangeException ("index");
1536 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1537 "Value has to be >= 0."));
1539 if (index + length > array.Length)
1540 throw new ArgumentException ();
1542 SortImpl<T, T> (array, null, index, length, comparer);
1545 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1546 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length, IComparer<TKey> comparer)
1548 if (items == null) {
1549 Sort<TKey> (keys, index, length, comparer);
1554 throw new ArgumentNullException ("keys");
1557 throw new ArgumentOutOfRangeException ("index");
1560 throw new ArgumentOutOfRangeException ("length");
1562 if (keys.Length != items.Length || keys.Length - index < length)
1563 throw new ArgumentException ();
1565 SortImpl<TKey, TValue> (keys, items, index, length, comparer);
1568 private static void SortImpl<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length, IComparer<TKey> comparer)
1570 if (keys.Length <= 1)
1574 // Check for value types which can be sorted without Compare () method
1576 if (comparer == null) {
1577 Swapper iswapper = (items != null ? get_swapper<TValue> (items) : null);
1578 if (keys is double[]) {
1579 combsort (keys as double[], index, length, iswapper);
1582 if (keys is int[]) {
1583 combsort (keys as int[], index, length, iswapper);
1586 if (keys is char[]) {
1587 combsort (keys as char[], index, length, iswapper);
1591 // Use Comparer<T>.Default instead
1592 // comparer = Comparer<K>.Default;
1596 int high = index + length - 1;
1597 low = MoveNullKeysToFront<TKey, TValue> (keys, items, low, high, comparer == null);
1602 qsort<TKey, TValue> (keys, items, low, high, comparer);
1603 } catch (Exception e) {
1604 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1608 public static void Sort<T> (T [] array, Comparison<T> comparison)
1611 throw new ArgumentNullException ("array");
1613 if (comparison == null)
1614 throw new ArgumentNullException ("comparison");
1616 SortImpl<T> (array, array.Length, comparison);
1619 // used by List<T>.Sort (Comparison <T>)
1620 internal static void SortImpl<T> (T [] array, int length, Comparison<T> comparison)
1627 int high0 = length - 1;
1628 qsort<T> (array, low0, high0, comparison);
1629 } catch (InvalidOperationException) {
1631 } catch (Exception e) {
1632 throw new InvalidOperationException (Locale.GetText ("Comparison threw an exception."), e);
1636 private static void qsort<K, V> (K [] keys, V [] items, int low0, int high0, IComparer<K> comparer)
1641 // Be careful with overflows
1642 int mid = low + ((high - low) / 2);
1643 K keyPivot = keys [mid];
1644 IComparable<K> genCmpPivot = keyPivot as IComparable<K>;
1645 IComparable cmpPivot = keyPivot as IComparable;
1648 // Move the walls in
1649 if (comparer != null) {
1650 while (low < high0 && comparer.Compare (keyPivot, keys [low]) > 0)
1652 while (high > low0 && comparer.Compare (keyPivot, keys [high]) < 0)
1655 if (genCmpPivot != null) {
1656 while (low < high0 && genCmpPivot.CompareTo (keys [low]) > 0)
1658 while (high > low0 && genCmpPivot.CompareTo (keys [high]) < 0)
1661 while (low < high0 && cmpPivot.CompareTo (keys [low]) > 0)
1663 while (high > low0 && cmpPivot.CompareTo (keys [high]) < 0)
1669 swap<K, V> (keys, items, low, high);
1677 qsort<K, V> (keys, items, low0, high, comparer);
1679 qsort<K, V> (keys, items, low, high0, comparer);
1682 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1687 // Be careful with overflows
1688 int mid = low + ((high - low) / 2);
1689 T keyPivot = array [mid];
1692 // Move the walls in
1693 while (low < high0 && comparison (array [low], keyPivot) < 0)
1695 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1699 swap<T> (array, low, high);
1707 qsort<T> (array, low0, high, comparison);
1709 qsort<T> (array, low, high0, comparison);
1712 private static int MoveNullKeysToFront<K, V> (K [] keys, V [] items, int low, int high, bool ensureComparable)
1714 // find first nun-null key
1715 while (low < high && keys [low] == null)
1718 // move null keys to beginning of array,
1719 // ensure that non-null keys implement IComparable
1720 for (int i = low + 1; i <= high; i++) {
1723 swap<K, V> (keys, items, low, i);
1726 if (ensureComparable && !(key is IComparable<K>) && !(key is IComparable)) {
1727 string msg = Locale.GetText ("No IComparable<T> or IComparable interface found for type '{0}'.");
1728 throw new InvalidOperationException (String.Format (msg, key.GetType ()));
1735 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1740 keys [i] = keys [j];
1743 if (items != null) {
1746 items [i] = items [j];
1751 private static void swap<T> (T [] array, int i, int j)
1754 array [i] = array [j];
1758 public void CopyTo (Array array, int index)
1761 throw new ArgumentNullException ("array");
1763 // The order of these exception checks may look strange,
1764 // but that's how the microsoft runtime does it.
1766 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1767 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1768 throw new ArgumentException ("Destination array was not long " +
1769 "enough. Check destIndex and length, and the array's " +
1772 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1774 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1775 "Value has to be >= 0."));
1777 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1780 [ComVisible (false)]
1781 public void CopyTo (Array array, long index)
1783 if (index < 0 || index > Int32.MaxValue)
1784 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1785 "Value must be >= 0 and <= Int32.MaxValue."));
1787 CopyTo (array, (int) index);
1790 internal class SimpleEnumerator : IEnumerator, ICloneable
1796 public SimpleEnumerator (Array arrayToEnumerate)
1798 this.enumeratee = arrayToEnumerate;
1799 this.currentpos = -1;
1800 this.length = arrayToEnumerate.Length;
1803 public object Current {
1805 // Exception messages based on MS implementation
1806 if (currentpos < 0 )
1807 throw new InvalidOperationException (Locale.GetText (
1808 "Enumeration has not started."));
1809 if (currentpos >= length)
1810 throw new InvalidOperationException (Locale.GetText (
1811 "Enumeration has already ended"));
1812 // Current should not increase the position. So no ++ over here.
1813 return enumeratee.GetValueImpl (currentpos);
1817 public bool MoveNext()
1819 //The docs say Current should throw an exception if last
1820 //call to MoveNext returned false. This means currentpos
1821 //should be set to length when returning false.
1822 if (currentpos < length)
1824 if(currentpos < length)
1835 public object Clone ()
1837 return MemberwiseClone ();
1841 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1842 public static void Resize<T> (ref T [] array, int newSize)
1844 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1847 internal static void Resize<T> (ref T[] array, int length, int newSize)
1850 throw new ArgumentOutOfRangeException ();
1852 if (array == null) {
1853 array = new T [newSize];
1857 if (array.Length == newSize)
1860 T [] a = new T [newSize];
1861 Array.Copy (array, a, Math.Min (newSize, length));
1865 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1868 throw new ArgumentNullException ("array");
1870 throw new ArgumentNullException ("match");
1872 foreach (T t in array)
1879 public static void ForEach<T> (T [] array, Action <T> action)
1882 throw new ArgumentNullException ("array");
1884 throw new ArgumentNullException ("action");
1886 foreach (T t in array)
1890 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1893 throw new ArgumentNullException ("array");
1894 if (converter == null)
1895 throw new ArgumentNullException ("converter");
1897 TOutput [] output = new TOutput [array.Length];
1898 for (int i = 0; i < array.Length; i ++)
1899 output [i] = converter (array [i]);
1904 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1907 throw new ArgumentNullException ("array");
1909 return FindLastIndex<T> (array, 0, array.Length, match);
1912 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1915 throw new ArgumentNullException ();
1917 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1920 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1923 throw new ArgumentNullException ("array");
1925 throw new ArgumentNullException ("match");
1927 if (startIndex > array.Length || startIndex + count > array.Length)
1928 throw new ArgumentOutOfRangeException ();
1930 for (int i = startIndex + count - 1; i >= startIndex; i--)
1931 if (match (array [i]))
1937 public static int FindIndex<T> (T [] array, Predicate<T> match)
1940 throw new ArgumentNullException ("array");
1942 return FindIndex<T> (array, 0, array.Length, match);
1945 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1948 throw new ArgumentNullException ("array");
1950 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1953 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1956 throw new ArgumentNullException ("array");
1959 throw new ArgumentNullException ("match");
1961 if (startIndex > array.Length || startIndex + count > array.Length)
1962 throw new ArgumentOutOfRangeException ();
1964 for (int i = startIndex; i < startIndex + count; i ++)
1965 if (match (array [i]))
1971 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1972 public static int BinarySearch<T> (T [] array, T value)
1975 throw new ArgumentNullException ("array");
1977 return BinarySearch<T> (array, 0, array.Length, value, null);
1980 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1981 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1984 throw new ArgumentNullException ("array");
1986 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1989 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1990 public static int BinarySearch<T> (T [] array, int index, int length, T value)
1992 return BinarySearch<T> (array, index, length, value, null);
1995 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1996 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1999 throw new ArgumentNullException ("array");
2001 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
2002 "index is less than the lower bound of array."));
2004 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
2005 "Value has to be >= 0."));
2006 // re-ordered to avoid possible integer overflow
2007 if (index > array.Length - length)
2008 throw new ArgumentException (Locale.GetText (
2009 "index and length do not specify a valid range in array."));
2010 if (comparer == null)
2011 comparer = Comparer <T>.Default;
2014 int iMax = index + length - 1;
2017 while (iMin <= iMax) {
2018 // Be careful with overflows
2019 int iMid = iMin + ((iMax - iMin) / 2);
2020 iCmp = comparer.Compare (value, array [iMid]);
2027 iMin = iMid + 1; // compensate for the rounding down
2029 } catch (Exception e) {
2030 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
2036 public static int IndexOf<T> (T [] array, T value)
2039 throw new ArgumentNullException ("array");
2041 return IndexOf<T> (array, value, 0, array.Length);
2044 public static int IndexOf<T> (T [] array, T value, int startIndex)
2047 throw new ArgumentNullException ("array");
2049 return IndexOf<T> (array, value, startIndex, array.Length - startIndex);
2052 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
2055 throw new ArgumentNullException ("array");
2057 // re-ordered to avoid possible integer overflow
2058 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
2059 throw new ArgumentOutOfRangeException ();
2061 int max = startIndex + count;
2062 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2063 for (int i = startIndex; i < max; i++) {
2064 if (equalityComparer.Equals (array [i], value))
2071 public static int LastIndexOf<T> (T [] array, T value)
2074 throw new ArgumentNullException ("array");
2076 if (array.Length == 0)
2078 return LastIndexOf<T> (array, value, array.Length - 1);
2081 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
2084 throw new ArgumentNullException ("array");
2086 return LastIndexOf<T> (array, value, startIndex, startIndex + 1);
2089 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
2092 throw new ArgumentNullException ("array");
2094 if (count < 0 || startIndex < array.GetLowerBound (0) ||
2095 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
2096 throw new ArgumentOutOfRangeException ();
2098 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2099 for (int i = startIndex; i >= startIndex - count + 1; i--) {
2100 if (equalityComparer.Equals (array [i], value))
2107 public static T [] FindAll<T> (T [] array, Predicate <T> match)
2110 throw new ArgumentNullException ("array");
2113 throw new ArgumentNullException ("match");
2116 T [] d = new T [array.Length];
2117 foreach (T t in array)
2121 Resize <T> (ref d, pos);
2125 public static bool Exists<T> (T [] array, Predicate <T> match)
2128 throw new ArgumentNullException ("array");
2131 throw new ArgumentNullException ("match");
2133 foreach (T t in array)
2139 public static ReadOnlyCollection<T> AsReadOnly<T> (T[] array)
2142 throw new ArgumentNullException ("array");
2143 return new ReadOnlyCollection<T> (new ArrayReadOnlyList<T> (array));
2146 public static T Find<T> (T [] array, Predicate<T> match)
2149 throw new ArgumentNullException ("array");
2152 throw new ArgumentNullException ("match");
2154 foreach (T t in array)
2161 public static T FindLast<T> (T [] array, Predicate <T> match)
2164 throw new ArgumentNullException ("array");
2167 throw new ArgumentNullException ("match");
2169 for (int i = array.Length - 1; i >= 0; i--)
2170 if (match (array [i]))
2176 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
2178 // The constrained copy should guarantee that if there is an exception thrown
2179 // during the copy, the destination array remains unchanged.
2180 // This is related to System.Runtime.Reliability.CER
2181 public static void ConstrainedCopy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
2183 Copy (sourceArray, sourceIndex, destinationArray, destinationIndex, length);
2186 class ArrayReadOnlyList<T> : IList<T>
2190 public ArrayReadOnlyList (T [] array)
2195 public T this [int index] {
2197 if (unchecked ((uint) index) >= unchecked ((uint) array.Length))
2198 throw new ArgumentOutOfRangeException ("index");
2199 return array [index];
2201 set { throw ReadOnlyError (); }
2205 get { return array.Length; }
2208 public bool IsReadOnly {
2209 get { return true; }
2212 public void Add (T item)
2214 throw ReadOnlyError ();
2217 public void Clear ()
2219 throw ReadOnlyError ();
2222 public bool Contains (T item)
2224 return Array.IndexOf<T> (array, item) >= 0;
2227 public void CopyTo (T [] array, int index)
2229 array.CopyTo (array, index);
2232 IEnumerator IEnumerable.GetEnumerator ()
2234 return GetEnumerator ();
2237 public IEnumerator<T> GetEnumerator ()
2239 for (int i = 0; i < array.Length; i++)
2240 yield return array [i];
2243 public int IndexOf (T item)
2245 return Array.IndexOf<T> (array, item);
2248 public void Insert (int index, T item)
2250 throw ReadOnlyError ();
2253 public bool Remove (T item)
2255 throw ReadOnlyError ();
2258 public void RemoveAt (int index)
2260 throw ReadOnlyError ();
2263 static Exception ReadOnlyError ()
2265 return new NotSupportedException ("This collection is read-only.");