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;
38 using System.Collections.Generic;
39 using System.Runtime.ConstrainedExecution;
46 [MonoTODO ("We are doing way to many double/triple exception checks for the overloaded functions")]
47 [MonoTODO ("Sort overloads parameter checks are VERY inconsistent")]
48 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
58 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
61 int length = this.GetLength (0);
63 for (int i = 1; i < this.Rank; i++) {
64 length *= this.GetLength (i);
72 public long LongLength {
74 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
76 get { return Length; }
82 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
85 return this.GetRank ();
90 object IList.this [int index] {
92 if (unchecked ((uint) index) >= unchecked ((uint) Length))
93 throw new ArgumentOutOfRangeException ("index");
94 return GetValueImpl (index);
97 if (unchecked ((uint) index) >= unchecked ((uint) Length))
98 throw new ArgumentOutOfRangeException ("index");
99 SetValueImpl (value, index);
103 int IList.Add (object value)
105 throw new NotSupportedException ();
110 Array.Clear (this, this.GetLowerBound (0), this.Length);
113 bool IList.Contains (object value)
116 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
118 int length = this.Length;
119 for (int i = 0; i < length; i++) {
120 if (Object.Equals (value, this.GetValueImpl (i)))
127 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
129 int IList.IndexOf (object value)
132 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
134 int length = this.Length;
135 for (int i = 0; i < length; i++) {
136 if (Object.Equals (value, this.GetValueImpl (i)))
137 // array index may not be zero-based.
139 return i + this.GetLowerBound (0);
144 // lower bound may be MinValue
145 retVal = this.GetLowerBound (0) - 1;
151 void IList.Insert (int index, object value)
153 throw new NotSupportedException ();
156 void IList.Remove (object value)
158 throw new NotSupportedException ();
161 void IList.RemoveAt (int index)
163 throw new NotSupportedException ();
166 // InternalCall Methods
167 [MethodImplAttribute (MethodImplOptions.InternalCall)]
168 private extern int GetRank ();
170 [MethodImplAttribute (MethodImplOptions.InternalCall)]
171 public extern int GetLength (int dimension);
175 public long GetLongLength (int dimension)
177 return GetLength (dimension);
182 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
184 [MethodImplAttribute (MethodImplOptions.InternalCall)]
185 public extern int GetLowerBound (int dimension);
187 [MethodImplAttribute (MethodImplOptions.InternalCall)]
188 public extern object GetValue (params int[] indices);
190 [MethodImplAttribute (MethodImplOptions.InternalCall)]
191 public extern void SetValue (object value, params int[] indices);
193 // CAUTION! No bounds checking!
194 [MethodImplAttribute (MethodImplOptions.InternalCall)]
195 internal extern object GetValueImpl (int pos);
197 // CAUTION! No bounds checking!
198 [MethodImplAttribute (MethodImplOptions.InternalCall)]
199 internal extern void SetValueImpl (object value, int pos);
201 [MethodImplAttribute (MethodImplOptions.InternalCall)]
202 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
204 [MethodImplAttribute (MethodImplOptions.InternalCall)]
205 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
208 int ICollection.Count {
214 public virtual bool IsSynchronized {
220 public virtual object SyncRoot {
226 public virtual bool IsFixedSize {
232 public virtual bool IsReadOnly {
238 public virtual IEnumerator GetEnumerator ()
240 return new SimpleEnumerator (this);
244 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
246 public int GetUpperBound (int dimension)
248 return GetLowerBound (dimension) + GetLength (dimension) - 1;
251 public object GetValue (int index)
254 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
255 if (index < GetLowerBound (0) || index > GetUpperBound (0))
256 throw new IndexOutOfRangeException (Locale.GetText (
257 "Index has to be between upper and lower bound of the array."));
259 return GetValueImpl (index - GetLowerBound (0));
262 public object GetValue (int index1, int index2)
264 int[] ind = {index1, index2};
265 return GetValue (ind);
268 public object GetValue (int index1, int index2, int index3)
270 int[] ind = {index1, index2, index3};
271 return GetValue (ind);
276 public object GetValue (long index)
278 if (index < 0 || index > Int32.MaxValue)
279 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
280 "Value must be >= 0 and <= Int32.MaxValue."));
282 return GetValue ((int) index);
286 public object GetValue (long index1, long index2)
288 if (index1 < 0 || index1 > Int32.MaxValue)
289 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
290 "Value must be >= 0 and <= Int32.MaxValue."));
292 if (index2 < 0 || index2 > Int32.MaxValue)
293 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
294 "Value must be >= 0 and <= Int32.MaxValue."));
296 return GetValue ((int) index1, (int) index2);
300 public object GetValue (long index1, long index2, long index3)
302 if (index1 < 0 || index1 > Int32.MaxValue)
303 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
304 "Value must be >= 0 and <= Int32.MaxValue."));
306 if (index2 < 0 || index2 > Int32.MaxValue)
307 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
308 "Value must be >= 0 and <= Int32.MaxValue."));
310 if (index3 < 0 || index3 > Int32.MaxValue)
311 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
312 "Value must be >= 0 and <= Int32.MaxValue."));
314 return GetValue ((int) index1, (int) index2, (int) index3);
318 public void SetValue (object value, long index)
320 if (index < 0 || index > Int32.MaxValue)
321 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
322 "Value must be >= 0 and <= Int32.MaxValue."));
324 SetValue (value, (int) index);
328 public void SetValue (object value, long index1, long index2)
330 if (index1 < 0 || index1 > Int32.MaxValue)
331 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
332 "Value must be >= 0 and <= Int32.MaxValue."));
334 if (index2 < 0 || index2 > Int32.MaxValue)
335 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
336 "Value must be >= 0 and <= Int32.MaxValue."));
338 int[] ind = {(int) index1, (int) index2};
339 SetValue (value, ind);
343 public void SetValue (object value, long index1, long index2, long index3)
345 if (index1 < 0 || index1 > Int32.MaxValue)
346 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
347 "Value must be >= 0 and <= Int32.MaxValue."));
349 if (index2 < 0 || index2 > Int32.MaxValue)
350 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
351 "Value must be >= 0 and <= Int32.MaxValue."));
353 if (index3 < 0 || index3 > Int32.MaxValue)
354 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
355 "Value must be >= 0 and <= Int32.MaxValue."));
357 int[] ind = {(int) index1, (int) index2, (int) index3};
358 SetValue (value, ind);
362 public void SetValue (object value, int index)
365 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
366 if (index < GetLowerBound (0) || index > GetUpperBound (0))
367 throw new IndexOutOfRangeException (Locale.GetText (
368 "Index has to be >= lower bound and <= upper bound of the array."));
370 SetValueImpl (value, index - GetLowerBound (0));
373 public void SetValue (object value, int index1, int index2)
375 int[] ind = {index1, index2};
376 SetValue (value, ind);
379 public void SetValue (object value, int index1, int index2, int index3)
381 int[] ind = {index1, index2, index3};
382 SetValue (value, ind);
385 public static Array CreateInstance (Type elementType, int length)
387 int[] lengths = {length};
389 return CreateInstance (elementType, lengths);
392 public static Array CreateInstance (Type elementType, int length1, int length2)
394 int[] lengths = {length1, length2};
396 return CreateInstance (elementType, lengths);
399 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
401 int[] lengths = {length1, length2, length3};
403 return CreateInstance (elementType, lengths);
406 public static Array CreateInstance (Type elementType, int[] lengths)
408 if (elementType == null)
409 throw new ArgumentNullException ("elementType");
411 throw new ArgumentNullException ("lengths");
413 if (lengths.Length > 255)
414 throw new TypeLoadException ();
418 elementType = elementType.UnderlyingSystemType;
419 if (!elementType.IsSystemType)
420 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
422 return CreateInstanceImpl (elementType, lengths, bounds);
425 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
427 if (elementType == null)
428 throw new ArgumentNullException ("elementType");
430 throw new ArgumentNullException ("lengths");
432 throw new ArgumentNullException ("bounds");
434 elementType = elementType.UnderlyingSystemType;
435 if (!elementType.IsSystemType)
436 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
438 if (lengths.Length < 1)
439 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
441 if (lengths.Length != bounds.Length)
442 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
444 for (int j = 0; j < bounds.Length; j ++) {
446 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
447 "Each value has to be >= 0."));
448 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
449 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
450 "Length + bound must not exceed Int32.MaxValue."));
453 if (lengths.Length > 255)
454 throw new TypeLoadException ();
456 return CreateInstanceImpl (elementType, lengths, bounds);
460 static int [] GetIntArray (long [] values)
462 int len = values.Length;
463 int [] ints = new int [len];
464 for (int i = 0; i < len; i++) {
465 long current = values [i];
466 if (current < 0 || current > (long) Int32.MaxValue)
467 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
468 "Each value has to be >= 0 and <= Int32.MaxValue."));
470 ints [i] = (int) current;
475 public static Array CreateInstance (Type elementType, params long [] lengths)
479 throw new ArgumentNullException ("lengths");
481 return CreateInstance (elementType, GetIntArray (lengths));
485 public object GetValue (params long [] indices)
489 throw new ArgumentNullException ("indices");
491 return GetValue (GetIntArray (indices));
495 public void SetValue (object value, params long [] indices)
499 throw new ArgumentNullException ("indices");
501 SetValue (value, GetIntArray (indices));
506 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
508 public static int BinarySearch (Array array, object value)
511 throw new ArgumentNullException ("array");
517 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
519 if (array.Length == 0)
522 if (!(value is IComparable))
523 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
525 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
529 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
531 public static int BinarySearch (Array array, object value, IComparer comparer)
534 throw new ArgumentNullException ("array");
537 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
539 if (array.Length == 0)
542 if ((comparer == null) && (value != null) && !(value is IComparable))
543 throw new ArgumentException (Locale.GetText (
544 "comparer is null and value does not support IComparable."));
546 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
550 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
552 public static int BinarySearch (Array array, int index, int length, object value)
555 throw new ArgumentNullException ("array");
558 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
560 if (index < array.GetLowerBound (0))
561 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
562 "index is less than the lower bound of array."));
564 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
565 "Value has to be >= 0."));
566 // re-ordered to avoid possible integer overflow
567 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
568 throw new ArgumentException (Locale.GetText (
569 "index and length do not specify a valid range in array."));
571 if (array.Length == 0)
574 if ((value != null) && (!(value is IComparable)))
575 throw new ArgumentException (Locale.GetText (
576 "value does not support IComparable"));
578 return DoBinarySearch (array, index, length, value, null);
582 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
584 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
587 throw new ArgumentNullException ("array");
590 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
592 if (index < array.GetLowerBound (0))
593 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
594 "index is less than the lower bound of array."));
596 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
597 "Value has to be >= 0."));
598 // re-ordered to avoid possible integer overflow
599 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
600 throw new ArgumentException (Locale.GetText (
601 "index and length do not specify a valid range in array."));
603 if (array.Length == 0)
606 if ((comparer == null) && (value != null) && !(value is IComparable))
607 throw new ArgumentException (Locale.GetText (
608 "comparer is null and value does not support IComparable."));
610 return DoBinarySearch (array, index, length, value, comparer);
613 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
615 // cache this in case we need it
616 if (comparer == null)
617 comparer = Comparer.Default;
620 // Comment from Tum (tum@veridicus.com):
621 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
622 int iMax = index + length - 1;
625 while (iMin <= iMax) {
626 int iMid = (iMin + iMax) / 2;
627 object elt = array.GetValueImpl (iMid);
629 iCmp = comparer.Compare (elt, value);
636 iMin = iMid + 1; // compensate for the rounding down
639 catch (Exception e) {
640 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
647 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
649 public static void Clear (Array array, int index, int length)
652 throw new ArgumentNullException ("array");
654 throw new ArgumentOutOfRangeException ("length < 0");
656 int low = array.GetLowerBound (0);
658 throw new IndexOutOfRangeException ("index < lower bound");
661 // re-ordered to avoid possible integer overflow
662 if (index > array.Length - length)
663 throw new IndexOutOfRangeException ("index + length > size");
665 ClearInternal (array, index, length);
668 [MethodImplAttribute (MethodImplOptions.InternalCall)]
669 static extern void ClearInternal (Array a, int index, int count);
671 [MethodImplAttribute (MethodImplOptions.InternalCall)]
672 public virtual extern object Clone ();
675 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
677 public static void Copy (Array sourceArray, Array destinationArray, int length)
679 // need these checks here because we are going to use
680 // GetLowerBound() on source and dest.
681 if (sourceArray == null)
682 throw new ArgumentNullException ("sourceArray");
684 if (destinationArray == null)
685 throw new ArgumentNullException ("destinationArray");
687 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
688 destinationArray.GetLowerBound (0), length);
692 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
694 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
696 if (sourceArray == null)
697 throw new ArgumentNullException ("sourceArray");
699 if (destinationArray == null)
700 throw new ArgumentNullException ("destinationArray");
703 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
704 "Value has to be >= 0."));;
707 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
708 "Value has to be >= 0."));;
710 if (destinationIndex < 0)
711 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
712 "Value has to be >= 0."));;
714 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
717 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
718 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
720 // re-ordered to avoid possible integer overflow
721 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
722 throw new ArgumentException ("length");
724 if (sourceArray.Rank != destinationArray.Rank)
725 throw new RankException (Locale.GetText ("Arrays must be of same size."));
727 Type src_type = sourceArray.GetType ().GetElementType ();
728 Type dst_type = destinationArray.GetType ().GetElementType ();
730 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
731 for (int i = 0; i < length; i++) {
732 Object srcval = sourceArray.GetValueImpl (source_pos + i);
735 destinationArray.SetValueImpl (srcval, dest_pos + i);
737 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
738 (src_type.Equals (typeof (Object))))
739 throw new InvalidCastException ();
741 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
742 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
747 for (int i = length - 1; i >= 0; i--) {
748 Object srcval = sourceArray.GetValueImpl (source_pos + i);
751 destinationArray.SetValueImpl (srcval, dest_pos + i);
753 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
754 (src_type.Equals (typeof (Object))))
755 throw new InvalidCastException ();
757 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
758 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
766 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
768 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
769 long destinationIndex, long length)
771 if (sourceArray == null)
772 throw new ArgumentNullException ("sourceArray");
774 if (destinationArray == null)
775 throw new ArgumentNullException ("destinationArray");
777 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
778 throw new ArgumentOutOfRangeException ("sourceIndex",
779 Locale.GetText ("Must be in the Int32 range."));
781 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
782 throw new ArgumentOutOfRangeException ("destinationIndex",
783 Locale.GetText ("Must be in the Int32 range."));
785 if (length < 0 || length > Int32.MaxValue)
786 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
787 "Value must be >= 0 and <= Int32.MaxValue."));
789 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
793 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
795 public static void Copy (Array sourceArray, Array destinationArray, long length)
797 if (length < 0 || length > Int32.MaxValue)
798 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
799 "Value must be >= 0 and <= Int32.MaxValue."));
801 Copy (sourceArray, destinationArray, (int) length);
806 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
808 public static int IndexOf (Array array, object value)
811 throw new ArgumentNullException ("array");
813 return IndexOf (array, value, 0, array.Length);
817 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
819 public static int IndexOf (Array array, object value, int startIndex)
822 throw new ArgumentNullException ("array");
824 return IndexOf (array, value, startIndex, array.Length - startIndex);
828 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
830 public static int IndexOf (Array array, object value, int startIndex, int count)
833 throw new ArgumentNullException ("array");
836 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
838 // re-ordered to avoid possible integer overflow
839 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
840 throw new ArgumentOutOfRangeException ();
842 int max = startIndex + count;
843 for (int i = startIndex; i < max; i++) {
844 if (Object.Equals (value, array.GetValueImpl (i)))
848 return array.GetLowerBound (0) - 1;
852 public void Initialize()
854 //FIXME: We would like to find a compiler that uses
855 // this method. It looks like this method do nothing
856 // in C# so no exception is trown by the moment.
860 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
862 public static int LastIndexOf (Array array, object value)
865 throw new ArgumentNullException ("array");
867 return LastIndexOf (array, value, array.Length - 1);
871 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
873 public static int LastIndexOf (Array array, object value, int startIndex)
876 throw new ArgumentNullException ("array");
878 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
882 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
884 public static int LastIndexOf (Array array, object value, int startIndex, int count)
887 throw new ArgumentNullException ("array");
890 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
892 if (count < 0 || startIndex < array.GetLowerBound (0) ||
893 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
894 throw new ArgumentOutOfRangeException ();
896 for (int i = startIndex; i >= startIndex - count + 1; i--) {
897 if (Object.Equals (value, array.GetValueImpl (i)))
901 return array.GetLowerBound (0) - 1;
904 #if !BOOTSTRAP_WITH_OLDLIB
905 /* delegate used to swap array elements */
906 delegate void Swapper (int i, int j);
909 static Swapper get_swapper (Array array)
912 return new Swapper (array.int_swapper);
913 if (array is double[])
914 return new Swapper (array.double_swapper);
915 if (array is object[]) {
916 return new Swapper (array.obj_swapper);
918 return new Swapper (array.slow_swapper);
922 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
924 public static void Reverse (Array array)
927 throw new ArgumentNullException ("array");
929 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
933 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
935 public static void Reverse (Array array, int index, int length)
938 throw new ArgumentNullException ("array");
941 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
943 if (index < array.GetLowerBound (0) || length < 0)
944 throw new ArgumentOutOfRangeException ();
946 // re-ordered to avoid possible integer overflow
947 if (index > array.GetUpperBound (0) + 1 - length)
948 throw new ArgumentException ();
950 int end = index + length - 1;
951 object[] oarray = array as object[];
952 if (oarray != null) {
953 while (index < end) {
954 object tmp = oarray [index];
955 oarray [index] = oarray [end];
962 int[] iarray = array as int[];
963 if (iarray != null) {
964 while (index < end) {
965 int tmp = iarray [index];
966 iarray [index] = iarray [end];
973 double[] darray = array as double[];
974 if (darray != null) {
975 while (index < end) {
976 double tmp = darray [index];
977 darray [index] = darray [end];
985 Swapper swapper = get_swapper (array);
986 while (index < end) {
987 swapper (index, end);
994 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
996 public static void Sort (Array array)
999 throw new ArgumentNullException ("array");
1001 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
1005 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1007 public static void Sort (Array keys, Array items)
1010 throw new ArgumentNullException ("keys");
1012 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1016 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1018 public static void Sort (Array array, IComparer comparer)
1021 throw new ArgumentNullException ("array");
1023 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1027 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1029 public static void Sort (Array array, int index, int length)
1031 Sort (array, null, index, length, null);
1035 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1037 public static void Sort (Array keys, Array items, IComparer comparer)
1040 throw new ArgumentNullException ("keys");
1042 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1046 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1048 public static void Sort (Array keys, Array items, int index, int length)
1050 Sort (keys, items, index, length, null);
1054 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1056 public static void Sort (Array array, int index, int length, IComparer comparer)
1058 Sort (array, null, index, length, comparer);
1062 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1065 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1068 throw new ArgumentNullException ("keys");
1070 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1071 throw new RankException ();
1073 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1074 throw new ArgumentException ();
1076 if (index < keys.GetLowerBound (0))
1077 throw new ArgumentOutOfRangeException ("index");
1080 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1081 "Value has to be >= 0."));
1083 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1084 throw new ArgumentException ();
1089 if (comparer == null) {
1094 iswapper = get_swapper (items);
1095 if (keys is double[]) {
1096 combsort (keys as double[], index, length, iswapper);
1099 if (keys is int[]) {
1100 combsort (keys as int[], index, length, iswapper);
1103 if (keys is char[]) {
1104 combsort (keys as char[], index, length, iswapper);
1110 int high0 = index + length - 1;
1111 qsort (keys, items, low0, high0, comparer);
1113 catch (Exception e) {
1114 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1118 /* note, these are instance methods */
1119 void int_swapper (int i, int j) {
1120 int[] array = this as int[];
1121 int val = array [i];
1122 array [i] = array [j];
1126 void obj_swapper (int i, int j) {
1127 object[] array = this as object[];
1128 object val = array [i];
1129 array [i] = array [j];
1133 void slow_swapper (int i, int j) {
1134 object val = GetValueImpl (i);
1135 SetValueImpl (GetValue (j), i);
1136 SetValueImpl (val, j);
1139 void double_swapper (int i, int j) {
1140 double[] array = this as double[];
1141 double val = array [i];
1142 array [i] = array [j];
1146 static int new_gap (int gap)
1148 gap = (gap * 10) / 13;
1149 if (gap == 9 || gap == 10)
1156 /* we use combsort because it's fast enough and very small, since we have
1157 * several specialized versions here.
1159 static void combsort (double[] array, int start, int size, Swapper swap_items)
1163 gap = new_gap (gap);
1164 bool swapped = false;
1165 int end = start + size - gap;
1166 for (int i = start; i < end; i++) {
1168 if (array [i] > array [j]) {
1169 double val = array [i];
1170 array [i] = array [j];
1173 if (swap_items != null)
1177 if (gap == 1 && !swapped)
1182 static void combsort (int[] array, int start, int size, Swapper swap_items)
1186 gap = new_gap (gap);
1187 bool swapped = false;
1188 int end = start + size - gap;
1189 for (int i = start; i < end; i++) {
1191 if (array [i] > array [j]) {
1192 int val = array [i];
1193 array [i] = array [j];
1196 if (swap_items != null)
1200 if (gap == 1 && !swapped)
1205 static void combsort (char[] array, int start, int size, Swapper swap_items)
1209 gap = new_gap (gap);
1210 bool swapped = false;
1211 int end = start + size - gap;
1212 for (int i = start; i < end; i++) {
1214 if (array [i] > array [j]) {
1215 char val = array [i];
1216 array [i] = array [j];
1219 if (swap_items != null)
1223 if (gap == 1 && !swapped)
1228 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1236 object objPivot = keys.GetValueImpl ((low + high) / 2);
1238 while (low <= high) {
1239 // Move the walls in
1240 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1242 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1246 swap (keys, items, low, high);
1253 qsort (keys, items, low0, high, comparer);
1255 qsort (keys, items, low, high0, comparer);
1258 private static void swap (Array keys, Array items, int i, int j)
1262 tmp = keys.GetValueImpl (i);
1263 keys.SetValueImpl (keys.GetValue (j), i);
1264 keys.SetValueImpl (tmp, j);
1266 if (items != null) {
1267 tmp = items.GetValueImpl (i);
1268 items.SetValueImpl (items.GetValueImpl (j), i);
1269 items.SetValueImpl (tmp, j);
1273 private static int compare (object value1, object value2, IComparer comparer)
1276 return value2 == null ? 0 : -1;
1277 else if (value2 == null)
1279 else if (comparer == null)
1280 return ((IComparable) value1).CompareTo (value2);
1282 return comparer.Compare (value1, value2);
1285 public virtual void CopyTo (Array array, int index)
1288 throw new ArgumentNullException ("array");
1290 // The order of these exception checks may look strange,
1291 // but that's how the microsoft runtime does it.
1293 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1294 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1295 throw new ArgumentException ();
1297 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1299 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1300 "Value has to be >= 0."));
1302 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1306 [ComVisible (false)]
1307 public virtual void CopyTo (Array array, long index)
1309 if (index < 0 || index > Int32.MaxValue)
1310 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1311 "Value must be >= 0 and <= Int32.MaxValue."));
1313 CopyTo (array, (int) index);
1317 internal class SimpleEnumerator : IEnumerator, ICloneable
1323 public SimpleEnumerator (Array arrayToEnumerate)
1325 this.enumeratee = arrayToEnumerate;
1326 this.currentpos = -1;
1327 this.length = arrayToEnumerate.Length;
1330 public object Current {
1332 // Exception messages based on MS implementation
1333 if (currentpos < 0 )
1334 throw new InvalidOperationException (Locale.GetText (
1335 "Enumeration has not started."));
1336 if (currentpos >= length)
1337 throw new InvalidOperationException (Locale.GetText (
1338 "Enumeration has already ended"));
1339 // Current should not increase the position. So no ++ over here.
1340 return enumeratee.GetValueImpl (currentpos);
1344 public bool MoveNext()
1346 //The docs say Current should throw an exception if last
1347 //call to MoveNext returned false. This means currentpos
1348 //should be set to length when returning false.
1349 if (currentpos < length)
1351 if(currentpos < length)
1362 public object Clone ()
1364 return MemberwiseClone ();
1369 public static void Resize<T> (ref T [] array, int newSize)
1371 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1374 internal static void Resize<T> (ref T[] array, int length, int newSize)
1377 throw new ArgumentOutOfRangeException ();
1379 if (array == null) {
1380 array = new T [newSize];
1384 if (array.Length == newSize)
1387 T [] a = new T [newSize];
1388 Array.Copy (array, a, Math.Min (newSize, length));
1392 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1395 throw new ArgumentNullException ("array");
1397 throw new ArgumentNullException ("match");
1399 foreach (T t in array)
1406 public static void ForEach<T> (T [] array, Action <T> action)
1409 throw new ArgumentNullException ("array");
1411 throw new ArgumentNullException ("action");
1413 foreach (T t in array)
1417 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1420 throw new ArgumentNullException ("array");
1421 if (converter == null)
1422 throw new ArgumentNullException ("converter");
1424 TOutput [] output = new TOutput [array.Length];
1425 for (int i = 0; i < array.Length; i ++)
1426 output [i] = converter (array [i]);
1431 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1434 throw new ArgumentNullException ("array");
1436 return FindLastIndex<T> (array, 0, array.Length, match);
1439 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1442 throw new ArgumentNullException ();
1444 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1447 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1450 throw new ArgumentNullException ("array");
1452 throw new ArgumentNullException ("match");
1454 if (startIndex > array.Length || startIndex + count > array.Length)
1455 throw new ArgumentOutOfRangeException ();
1457 for (int i = startIndex + count - 1; i >= startIndex; i--)
1458 if (match (array [i]))
1464 public static int FindIndex<T> (T [] array, Predicate<T> match)
1467 throw new ArgumentNullException ("array");
1469 return FindIndex<T> (array, 0, array.Length, match);
1472 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1475 throw new ArgumentNullException ("array");
1477 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1480 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1483 throw new ArgumentNullException ("array");
1486 throw new ArgumentNullException ("match");
1488 if (startIndex > array.Length || startIndex + count > array.Length)
1489 throw new ArgumentOutOfRangeException ();
1491 for (int i = startIndex; i < startIndex + count; i ++)
1492 if (match (array [i]))
1498 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1499 public static int BinarySearch<T> (T [] array, T value)
1502 throw new ArgumentNullException ("array");
1504 return BinarySearch<T> (array, 0, array.Length, value, null);
1507 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1508 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1511 throw new ArgumentNullException ("array");
1513 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1516 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1518 return BinarySearch<T> (array, offset, length, value, null);
1521 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1522 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1525 throw new ArgumentNullException ("array");
1527 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1528 "index is less than the lower bound of array."));
1530 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1531 "Value has to be >= 0."));
1532 // re-ordered to avoid possible integer overflow
1533 if (index > array.Length - length)
1534 throw new ArgumentException (Locale.GetText (
1535 "index and length do not specify a valid range in array."));
1536 if (comparer == null)
1537 comparer = Comparer <T>.Default;
1540 int iMax = index + length - 1;
1543 while (iMin <= iMax) {
1544 int iMid = (iMin + iMax) / 2;
1545 iCmp = comparer.Compare (value, array [iMid]);
1552 iMin = iMid + 1; // compensate for the rounding down
1554 } catch (Exception e) {
1555 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1561 public static int IndexOf<T> (T [] array, T value)
1564 throw new ArgumentNullException ("array");
1566 return IndexOf (array, value, 0, array.Length);
1569 public static int IndexOf<T> (T [] array, T value, int startIndex)
1572 throw new ArgumentNullException ("array");
1574 return IndexOf (array, value, startIndex, array.Length - startIndex);
1577 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
1580 throw new ArgumentNullException ("array");
1582 // re-ordered to avoid possible integer overflow
1583 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1584 throw new ArgumentOutOfRangeException ();
1586 int max = startIndex + count;
1587 for (int i = startIndex; i < max; i++) {
1588 if (Object.Equals (value, array [i]))
1595 public static int LastIndexOf<T> (T [] array, T value)
1598 throw new ArgumentNullException ("array");
1600 return LastIndexOf (array, value, array.Length - 1);
1603 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
1606 throw new ArgumentNullException ("array");
1608 return LastIndexOf (array, value, startIndex, startIndex + 1);
1611 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
1614 throw new ArgumentNullException ("array");
1616 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1617 throw new ArgumentOutOfRangeException ();
1619 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1620 if (Object.Equals (value, array [i]))
1627 public static T [] FindAll<T> (T [] array, Predicate <T> match)
1630 throw new ArgumentNullException ("array");
1633 throw new ArgumentNullException ("match");
1636 T [] d = new T [array.Length];
1637 foreach (T t in array)
1641 Resize <T> (ref d, pos);
1645 public static bool Exists<T> (T [] array, Predicate <T> match)
1648 throw new ArgumentNullException ("array");
1651 throw new ArgumentNullException ("match");
1653 foreach (T t in array)
1659 public static IList<T> AsReadOnly<T> (T[] array)
1662 throw new ArgumentNullException ("array");
1663 return new ReadOnlyArray<T> (array);
1666 public static Nullable<T> Find<T> (T [] array, Predicate<T> match)
1669 throw new ArgumentNullException ("array");
1672 throw new ArgumentNullException ("match");
1674 foreach (T t in array)
1676 return new Nullable <T> (t);
1678 return default (Nullable <T>);
1681 public static Nullable<T> FindLast<T> (T [] array, Predicate <T> match)
1684 throw new ArgumentNullException ("array");
1687 throw new ArgumentNullException ("match");
1689 for (int i = array.Length - 1; i >= 0; i--)
1690 if (match (array [i]))
1691 return new Nullable <T> (array [i]);
1693 return default (Nullable <T>);
1696 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
1698 // The constrained copy should guarantee that if there is an exception thrown
1699 // during the copy, the destination array remains unchanged.
1700 // This is related to System.Runtime.Reliability.CER
1701 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1703 Copy (s, s_i, d, d_i, c);
1709 // This is used internally by the runtime to represent arrays; see #74953.
1711 // Note that you normally can't derive a class from System.Array (CS0644),
1712 // but GMCS makes an exception here for all classes which are nested inside
1715 internal class InternalArray<T> : Array, IList<T>
1717 new public IEnumerator<T> GetEnumerator ()
1719 return new InternalEnumerator (this);
1728 bool ICollection<T>.IsReadOnly {
1734 void ICollection<T>.Clear ()
1736 throw new NotSupportedException ("Collection is read-only");
1739 void ICollection<T>.Add (T item)
1741 throw new NotSupportedException ("Collection is read-only");
1744 bool ICollection<T>.Remove (T item)
1746 throw new NotSupportedException ("Collection is read-only");
1749 public bool Contains (T item)
1752 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1754 int length = this.Length;
1755 for (int i = 0; i < length; i++) {
1757 GetGenericValueImpl (i, out value);
1758 if (item.Equals (value))
1765 public void CopyTo (T[] array, int index)
1768 throw new ArgumentNullException ("array");
1770 // The order of these exception checks may look strange,
1771 // but that's how the microsoft runtime does it.
1773 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1774 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1775 throw new ArgumentException ();
1777 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1779 throw new ArgumentOutOfRangeException (
1780 "index", Locale.GetText ("Value has to be >= 0."));
1782 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1785 new public T this [int index] {
1787 if (unchecked ((uint) index) >= unchecked ((uint) Length))
1788 throw new ArgumentOutOfRangeException ("index");
1791 GetGenericValueImpl (index, out value);
1796 throw new NotSupportedException ("Collection is read-only");
1800 void IList<T>.Insert (int index, T item)
1802 throw new NotSupportedException ("Collection is read-only");
1805 void IList<T>.RemoveAt (int index)
1807 throw new NotSupportedException ("Collection is read-only");
1810 public int IndexOf (T item)
1813 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1815 int length = this.Length;
1816 for (int i = 0; i < length; i++) {
1818 GetGenericValueImpl (i, out value);
1819 if (item.Equals (value))
1820 // array index may not be zero-based.
1822 return i + this.GetLowerBound (0);
1827 // lower bound may be MinValue
1828 retVal = this.GetLowerBound (0) - 1;
1834 // CAUTION! No bounds checking!
1835 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1836 protected extern void GetGenericValueImpl (int pos, out T value);
1838 internal struct InternalEnumerator : IEnumerator<T>
1840 const int NOT_STARTED = -2;
1842 // this MUST be -1, because we depend on it in move next.
1843 // we just decr the size, so, 0 - 1 == FINISHED
1844 const int FINISHED = -1;
1846 InternalArray<T> array;
1849 internal InternalEnumerator (InternalArray<T> array)
1855 public void Dispose ()
1860 public bool MoveNext ()
1862 if (idx == NOT_STARTED)
1865 return idx != FINISHED && -- idx != FINISHED;
1871 throw new InvalidOperationException ();
1873 return array [array.Length - 1 - idx];
1877 void IEnumerator.Reset ()
1879 throw new NotImplementedException ();
1882 object IEnumerator.Current {
1894 internal struct ReadOnlyArrayEnumerator <T> : IEnumerator <T> {
1895 const int NOT_STARTED = -2;
1897 // this MUST be -1, because we depend on it in move next.
1898 // we just decr the size, so, 0 - 1 == FINISHED
1899 const int FINISHED = -1;
1901 ReadOnlyArray <T> array;
1904 internal ReadOnlyArrayEnumerator (ReadOnlyArray<T> array)
1910 public void Dispose ()
1915 public bool MoveNext ()
1917 if (idx == NOT_STARTED)
1920 return idx != FINISHED && -- idx != FINISHED;
1926 throw new InvalidOperationException ();
1928 return array [array.Count - 1 - idx];
1932 void IEnumerator.Reset ()
1934 throw new NotImplementedException ();
1937 object IEnumerator.Current {
1944 internal class ReadOnlyArray <T> : ICollection <T>, IList <T>, IEnumerable <T>
1948 internal ReadOnlyArray (T[] array) {
1952 // ICollection<T> interface
1959 public bool IsReadOnly {
1965 public void Add (T item) {
1966 throw new NotSupportedException ("Collection is read-only");
1969 public bool Remove (T item) {
1970 throw new NotSupportedException ("Collection is read-only");
1973 public void Clear () {
1974 throw new NotSupportedException ("Collection is read-only");
1977 public void CopyTo (T[] array, int index) {
1978 arr.CopyTo (array, index);
1981 public bool Contains (T item) {
1982 return Array.IndexOf <T> (arr, item) != -1;
1985 // IList<T> interface
1986 public T this [int index] {
1988 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
1989 throw new ArgumentOutOfRangeException ("index");
1993 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
1994 throw new ArgumentOutOfRangeException ("index");
1995 arr [index] = value;
1999 public void Insert (int index, T item) {
2000 throw new NotSupportedException ("Collection is read-only");
2003 public void RemoveAt (int index) {
2004 throw new NotSupportedException ("Collection is read-only");
2007 public int IndexOf (T item) {
2008 return Array.IndexOf <T> (arr, item);
2011 // IEnumerable<T> interface
2012 public IEnumerator<T> GetEnumerator () {
2013 return new ReadOnlyArrayEnumerator <T> (this);
2016 IEnumerator IEnumerable.GetEnumerator () {
2017 return new ReadOnlyArrayEnumerator <T> (this);
2022 #if BOOTSTRAP_WITH_OLDLIB
2023 /* delegate used to swap array elements, keep defined outside Array */
2024 delegate void Swapper (int i, int j);