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
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
41 using System.Collections.Generic;
42 using System.Runtime.ConstrainedExecution;
49 [MonoTODO ("We are doing way to many double/triple exception checks for the overloaded functions")]
50 [MonoTODO ("Sort overloads parameter checks are VERY inconsistent")]
51 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
61 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
64 int length = this.GetLength (0);
66 for (int i = 1; i < this.Rank; i++) {
67 length *= this.GetLength (i);
75 public long LongLength {
77 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
79 get { return Length; }
85 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
88 return this.GetRank ();
93 object IList.this [int index] {
95 if (unchecked ((uint) index) >= unchecked ((uint) Length))
96 throw new ArgumentOutOfRangeException ("index");
97 return GetValueImpl (index);
100 if (unchecked ((uint) index) >= unchecked ((uint) Length))
101 throw new ArgumentOutOfRangeException ("index");
102 SetValueImpl (value, index);
106 int IList.Add (object value)
108 throw new NotSupportedException ();
113 Array.Clear (this, this.GetLowerBound (0), this.Length);
116 bool IList.Contains (object value)
119 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
121 int length = this.Length;
122 for (int i = 0; i < length; i++) {
123 if (Object.Equals (value, this.GetValueImpl (i)))
130 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
132 int IList.IndexOf (object value)
135 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
137 int length = this.Length;
138 for (int i = 0; i < length; i++) {
139 if (Object.Equals (value, this.GetValueImpl (i)))
140 // array index may not be zero-based.
142 return i + this.GetLowerBound (0);
147 // lower bound may be MinValue
148 retVal = this.GetLowerBound (0) - 1;
154 void IList.Insert (int index, object value)
156 throw new NotSupportedException ();
159 void IList.Remove (object value)
161 throw new NotSupportedException ();
164 void IList.RemoveAt (int index)
166 throw new NotSupportedException ();
169 // InternalCall Methods
170 [MethodImplAttribute (MethodImplOptions.InternalCall)]
171 private extern int GetRank ();
173 [MethodImplAttribute (MethodImplOptions.InternalCall)]
174 public extern int GetLength (int dimension);
178 public long GetLongLength (int dimension)
180 return GetLength (dimension);
185 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
187 [MethodImplAttribute (MethodImplOptions.InternalCall)]
188 public extern int GetLowerBound (int dimension);
190 [MethodImplAttribute (MethodImplOptions.InternalCall)]
191 public extern object GetValue (int[] indices);
193 [MethodImplAttribute (MethodImplOptions.InternalCall)]
194 public extern void SetValue (object value, int[] indices);
196 // CAUTION! No bounds checking!
197 [MethodImplAttribute (MethodImplOptions.InternalCall)]
198 internal extern object GetValueImpl (int pos);
200 // CAUTION! No bounds checking!
201 [MethodImplAttribute (MethodImplOptions.InternalCall)]
202 internal extern void SetValueImpl (object value, int pos);
204 [MethodImplAttribute (MethodImplOptions.InternalCall)]
205 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
207 [MethodImplAttribute (MethodImplOptions.InternalCall)]
208 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
211 int ICollection.Count {
217 public virtual bool IsSynchronized {
223 public virtual object SyncRoot {
229 public virtual bool IsFixedSize {
235 public virtual bool IsReadOnly {
241 public virtual IEnumerator GetEnumerator ()
243 return new SimpleEnumerator (this);
247 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
249 public int GetUpperBound (int dimension)
251 return GetLowerBound (dimension) + GetLength (dimension) - 1;
254 public object GetValue (int index)
257 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
258 if (index < GetLowerBound (0) || index > GetUpperBound (0))
259 throw new IndexOutOfRangeException (Locale.GetText (
260 "Index has to be between upper and lower bound of the array."));
262 return GetValueImpl (index - GetLowerBound (0));
265 public object GetValue (int index1, int index2)
267 int[] ind = {index1, index2};
268 return GetValue (ind);
271 public object GetValue (int index1, int index2, int index3)
273 int[] ind = {index1, index2, index3};
274 return GetValue (ind);
279 public object GetValue (long index)
281 if (index < 0 || index > Int32.MaxValue)
282 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
283 "Value must be >= 0 and <= Int32.MaxValue."));
285 return GetValue ((int) index);
289 public object GetValue (long index1, long index2)
291 if (index1 < 0 || index1 > Int32.MaxValue)
292 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
293 "Value must be >= 0 and <= Int32.MaxValue."));
295 if (index2 < 0 || index2 > Int32.MaxValue)
296 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
297 "Value must be >= 0 and <= Int32.MaxValue."));
299 return GetValue ((int) index1, (int) index2);
303 public object GetValue (long index1, long index2, long index3)
305 if (index1 < 0 || index1 > Int32.MaxValue)
306 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
307 "Value must be >= 0 and <= Int32.MaxValue."));
309 if (index2 < 0 || index2 > Int32.MaxValue)
310 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
311 "Value must be >= 0 and <= Int32.MaxValue."));
313 if (index3 < 0 || index3 > Int32.MaxValue)
314 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
315 "Value must be >= 0 and <= Int32.MaxValue."));
317 return GetValue ((int) index1, (int) index2, (int) index3);
321 public void SetValue (object value, long index)
323 if (index < 0 || index > Int32.MaxValue)
324 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
325 "Value must be >= 0 and <= Int32.MaxValue."));
327 SetValue (value, (int) index);
331 public void SetValue (object value, long index1, long index2)
333 if (index1 < 0 || index1 > Int32.MaxValue)
334 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
335 "Value must be >= 0 and <= Int32.MaxValue."));
337 if (index2 < 0 || index2 > Int32.MaxValue)
338 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
339 "Value must be >= 0 and <= Int32.MaxValue."));
341 int[] ind = {(int) index1, (int) index2};
342 SetValue (value, ind);
346 public void SetValue (object value, long index1, long index2, long index3)
348 if (index1 < 0 || index1 > Int32.MaxValue)
349 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
350 "Value must be >= 0 and <= Int32.MaxValue."));
352 if (index2 < 0 || index2 > Int32.MaxValue)
353 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
354 "Value must be >= 0 and <= Int32.MaxValue."));
356 if (index3 < 0 || index3 > Int32.MaxValue)
357 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
358 "Value must be >= 0 and <= Int32.MaxValue."));
360 int[] ind = {(int) index1, (int) index2, (int) index3};
361 SetValue (value, ind);
365 public void SetValue (object value, int index)
368 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
369 if (index < GetLowerBound (0) || index > GetUpperBound (0))
370 throw new IndexOutOfRangeException (Locale.GetText (
371 "Index has to be >= lower bound and <= upper bound of the array."));
373 SetValueImpl (value, index - GetLowerBound (0));
376 public void SetValue (object value, int index1, int index2)
378 int[] ind = {index1, index2};
379 SetValue (value, ind);
382 public void SetValue (object value, int index1, int index2, int index3)
384 int[] ind = {index1, index2, index3};
385 SetValue (value, ind);
388 public static Array CreateInstance (Type elementType, int length)
390 int[] lengths = {length};
392 return CreateInstance (elementType, lengths);
395 public static Array CreateInstance (Type elementType, int length1, int length2)
397 int[] lengths = {length1, length2};
399 return CreateInstance (elementType, lengths);
402 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
404 int[] lengths = {length1, length2, length3};
406 return CreateInstance (elementType, lengths);
409 public static Array CreateInstance (Type elementType, int[] lengths)
411 if (elementType == null)
412 throw new ArgumentNullException ("elementType");
414 throw new ArgumentNullException ("lengths");
416 if (lengths.Length > 255)
417 throw new TypeLoadException ();
421 elementType = elementType.UnderlyingSystemType;
422 if (!elementType.IsSystemType)
423 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
425 return CreateInstanceImpl (elementType, lengths, bounds);
428 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
430 if (elementType == null)
431 throw new ArgumentNullException ("elementType");
433 throw new ArgumentNullException ("lengths");
435 throw new ArgumentNullException ("bounds");
437 elementType = elementType.UnderlyingSystemType;
438 if (!elementType.IsSystemType)
439 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
441 if (lengths.Length < 1)
442 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
444 if (lengths.Length != bounds.Length)
445 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
447 for (int j = 0; j < bounds.Length; j ++) {
449 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
450 "Each value has to be >= 0."));
451 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
452 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
453 "Length + bound must not exceed Int32.MaxValue."));
456 if (lengths.Length > 255)
457 throw new TypeLoadException ();
459 return CreateInstanceImpl (elementType, lengths, bounds);
463 static int [] GetIntArray (long [] values)
465 int len = values.Length;
466 int [] ints = new int [len];
467 for (int i = 0; i < len; i++) {
468 long current = values [i];
469 if (current < 0 || current > (long) Int32.MaxValue)
470 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
471 "Each value has to be >= 0 and <= Int32.MaxValue."));
473 ints [i] = (int) current;
478 public static Array CreateInstance (Type elementType, params long [] lengths)
480 if (lengths == null) {
481 // LAMESPEC: Docs say we should throw a ArgumentNull, but .NET
482 // 1.1 actually throws a NullReference.
483 throw new NullReferenceException (Locale.GetText ("'lengths' cannot be null."));
485 return CreateInstance (elementType, GetIntArray (lengths));
489 public object GetValue (long [] indices)
491 if (indices == null) {
492 // LAMESPEC: Docs say we should throw a ArgumentNull, but .NET
493 // 1.1 actually throws a NullReference.
494 throw new NullReferenceException (Locale.GetText ("'indices' cannot be null."));
496 return GetValue (GetIntArray (indices));
500 public void SetValue (object value, long [] indices)
502 if (indices == null) {
503 // LAMESPEC: Docs say we should throw a ArgumentNull, but .NET
504 // 1.1 actually throws a NullReference.
505 throw new NullReferenceException (Locale.GetText ("'indices' cannot be null."));
507 SetValue (value, GetIntArray (indices));
512 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
514 public static int BinarySearch (Array array, object value)
517 throw new ArgumentNullException ("array");
523 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
525 if (!(value is IComparable))
526 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
528 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
532 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
534 public static int BinarySearch (Array array, object value, IComparer comparer)
537 throw new ArgumentNullException ("array");
540 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
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."));
570 if ((value != null) && (!(value is IComparable)))
571 throw new ArgumentException (Locale.GetText (
572 "value does not support IComparable"));
574 return DoBinarySearch (array, index, length, value, null);
578 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
580 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
583 throw new ArgumentNullException ("array");
586 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
588 if (index < array.GetLowerBound (0))
589 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
590 "index is less than the lower bound of array."));
592 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
593 "Value has to be >= 0."));
594 // re-ordered to avoid possible integer overflow
595 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
596 throw new ArgumentException (Locale.GetText (
597 "index and length do not specify a valid range in array."));
599 if ((comparer == null) && (value != null) && !(value is IComparable))
600 throw new ArgumentException (Locale.GetText (
601 "comparer is null and value does not support IComparable."));
603 return DoBinarySearch (array, index, length, value, comparer);
606 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
608 // cache this in case we need it
609 if (comparer == null)
610 comparer = Comparer.Default;
613 // Comment from Tum (tum@veridicus.com):
614 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
615 int iMax = index + length - 1;
618 while (iMin <= iMax) {
619 int iMid = (iMin + iMax) / 2;
620 object elt = array.GetValueImpl (iMid);
622 iCmp = comparer.Compare (elt, value);
629 iMin = iMid + 1; // compensate for the rounding down
632 catch (Exception e) {
633 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
640 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
642 public static void Clear (Array array, int index, int length)
645 throw new ArgumentNullException ("array");
647 throw new ArgumentOutOfRangeException ("length < 0");
649 int low = array.GetLowerBound (0);
651 throw new IndexOutOfRangeException ("index < lower bound");
654 // re-ordered to avoid possible integer overflow
655 if (index > array.Length - length)
656 throw new IndexOutOfRangeException ("index + length > size");
658 ClearInternal (array, index, length);
661 [MethodImplAttribute (MethodImplOptions.InternalCall)]
662 static extern void ClearInternal (Array a, int index, int count);
664 [MethodImplAttribute (MethodImplOptions.InternalCall)]
665 public virtual extern object Clone ();
668 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
670 public static void Copy (Array sourceArray, Array destinationArray, int length)
672 // need these checks here because we are going to use
673 // GetLowerBound() on source and dest.
674 if (sourceArray == null)
675 throw new ArgumentNullException ("sourceArray");
677 if (destinationArray == null)
678 throw new ArgumentNullException ("destinationArray");
680 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
681 destinationArray.GetLowerBound (0), length);
685 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
687 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
689 if (sourceArray == null)
690 throw new ArgumentNullException ("sourceArray");
692 if (destinationArray == null)
693 throw new ArgumentNullException ("destinationArray");
696 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
697 "Value has to be >= 0."));;
700 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
701 "Value has to be >= 0."));;
703 if (destinationIndex < 0)
704 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
705 "Value has to be >= 0."));;
707 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
710 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
711 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
713 // re-ordered to avoid possible integer overflow
714 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
715 throw new ArgumentException ("length");
717 if (sourceArray.Rank != destinationArray.Rank)
718 throw new RankException (Locale.GetText ("Arrays must be of same size."));
720 Type src_type = sourceArray.GetType ().GetElementType ();
721 Type dst_type = destinationArray.GetType ().GetElementType ();
723 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
724 for (int i = 0; i < length; i++) {
725 Object srcval = sourceArray.GetValueImpl (source_pos + i);
728 destinationArray.SetValueImpl (srcval, dest_pos + i);
730 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
731 (src_type.Equals (typeof (Object))))
732 throw new InvalidCastException ();
734 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
735 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
740 for (int i = length - 1; i >= 0; i--) {
741 Object srcval = sourceArray.GetValueImpl (source_pos + i);
744 destinationArray.SetValueImpl (srcval, dest_pos + i);
746 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
747 (src_type.Equals (typeof (Object))))
748 throw new InvalidCastException ();
750 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
751 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
759 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
761 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
762 long destinationIndex, long length)
764 if (sourceArray == null)
765 throw new ArgumentNullException ("sourceArray");
767 if (destinationArray == null)
768 throw new ArgumentNullException ("destinationArray");
770 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
771 throw new ArgumentOutOfRangeException ("sourceIndex",
772 Locale.GetText ("Must be in the Int32 range."));
774 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
775 throw new ArgumentOutOfRangeException ("destinationIndex",
776 Locale.GetText ("Must be in the Int32 range."));
778 if (length < 0 || length > Int32.MaxValue)
779 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
780 "Value must be >= 0 and <= Int32.MaxValue."));
782 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
786 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
788 public static void Copy (Array sourceArray, Array destinationArray, long length)
790 if (length < 0 || length > Int32.MaxValue)
791 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
792 "Value must be >= 0 and <= Int32.MaxValue."));
794 Copy (sourceArray, destinationArray, (int) length);
799 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
801 public static int IndexOf (Array array, object value)
804 throw new ArgumentNullException ("array");
806 return IndexOf (array, value, 0, array.Length);
810 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
812 public static int IndexOf (Array array, object value, int startIndex)
815 throw new ArgumentNullException ("array");
817 return IndexOf (array, value, startIndex, array.Length - startIndex);
821 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
823 public static int IndexOf (Array array, object value, int startIndex, int count)
826 throw new ArgumentNullException ("array");
829 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
831 // re-ordered to avoid possible integer overflow
832 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
833 throw new ArgumentOutOfRangeException ();
835 int max = startIndex + count;
836 for (int i = startIndex; i < max; i++) {
837 if (Object.Equals (value, array.GetValueImpl (i)))
841 return array.GetLowerBound (0) - 1;
845 public void Initialize()
847 //FIXME: We would like to find a compiler that uses
848 // this method. It looks like this method do nothing
849 // in C# so no exception is trown by the moment.
853 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
855 public static int LastIndexOf (Array array, object value)
858 throw new ArgumentNullException ("array");
860 return LastIndexOf (array, value, array.Length - 1);
864 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
866 public static int LastIndexOf (Array array, object value, int startIndex)
869 throw new ArgumentNullException ("array");
871 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
875 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
877 public static int LastIndexOf (Array array, object value, int startIndex, int count)
880 throw new ArgumentNullException ("array");
883 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
885 if (count < 0 || startIndex < array.GetLowerBound (0) ||
886 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
887 throw new ArgumentOutOfRangeException ();
889 for (int i = startIndex; i >= startIndex - count + 1; i--) {
890 if (Object.Equals (value, array.GetValueImpl (i)))
894 return array.GetLowerBound (0) - 1;
897 #if !BOOTSTRAP_WITH_OLDLIB && !NET_2_0
898 /* delegate used to swap array elements */
899 delegate void Swapper (int i, int j);
902 static Swapper get_swapper (Array array)
905 return new Swapper (array.int_swapper);
906 if (array is double[])
907 return new Swapper (array.double_swapper);
908 if (array is object[]) {
909 return new Swapper (array.obj_swapper);
911 return new Swapper (array.slow_swapper);
915 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
917 public static void Reverse (Array array)
920 throw new ArgumentNullException ("array");
922 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
926 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
928 public static void Reverse (Array array, int index, int length)
931 throw new ArgumentNullException ("array");
934 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
936 if (index < array.GetLowerBound (0) || length < 0)
937 throw new ArgumentOutOfRangeException ();
939 // re-ordered to avoid possible integer overflow
940 if (index > array.GetUpperBound (0) + 1 - length)
941 throw new ArgumentException ();
943 int end = index + length - 1;
944 object[] oarray = array as object[];
945 if (oarray != null) {
946 while (index < end) {
947 object tmp = oarray [index];
948 oarray [index] = oarray [end];
955 int[] iarray = array as int[];
956 if (iarray != null) {
957 while (index < end) {
958 int tmp = iarray [index];
959 iarray [index] = iarray [end];
966 double[] darray = array as double[];
967 if (darray != null) {
968 while (index < end) {
969 double tmp = darray [index];
970 darray [index] = darray [end];
978 Swapper swapper = get_swapper (array);
979 while (index < end) {
980 swapper (index, end);
987 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
989 public static void Sort (Array array)
992 throw new ArgumentNullException ("array");
994 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
998 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1000 public static void Sort (Array keys, Array items)
1003 throw new ArgumentNullException ("keys");
1005 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1009 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1011 public static void Sort (Array array, IComparer comparer)
1014 throw new ArgumentNullException ("array");
1016 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1020 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1022 public static void Sort (Array array, int index, int length)
1024 Sort (array, null, index, length, null);
1028 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1030 public static void Sort (Array keys, Array items, IComparer comparer)
1033 throw new ArgumentNullException ("keys");
1035 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1039 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1041 public static void Sort (Array keys, Array items, int index, int length)
1043 Sort (keys, items, index, length, null);
1047 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1049 public static void Sort (Array array, int index, int length, IComparer comparer)
1051 Sort (array, null, index, length, comparer);
1055 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1058 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1061 throw new ArgumentNullException ("keys");
1063 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1064 throw new RankException ();
1066 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1067 throw new ArgumentException ();
1069 if (index < keys.GetLowerBound (0))
1070 throw new ArgumentOutOfRangeException ("index");
1073 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1074 "Value has to be >= 0."));
1076 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1077 throw new ArgumentException ();
1082 if (comparer == null) {
1087 iswapper = get_swapper (items);
1088 if (keys is double[]) {
1089 combsort (keys as double[], index, length, iswapper);
1092 if (keys is int[]) {
1093 combsort (keys as int[], index, length, iswapper);
1096 if (keys is char[]) {
1097 combsort (keys as char[], index, length, iswapper);
1103 int high0 = index + length - 1;
1104 qsort (keys, items, low0, high0, comparer);
1106 catch (Exception e) {
1107 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1111 /* note, these are instance methods */
1112 void int_swapper (int i, int j) {
1113 int[] array = this as int[];
1114 int val = array [i];
1115 array [i] = array [j];
1119 void obj_swapper (int i, int j) {
1120 object[] array = this as object[];
1121 object val = array [i];
1122 array [i] = array [j];
1126 void slow_swapper (int i, int j) {
1127 object val = GetValueImpl (i);
1128 SetValueImpl (GetValue (j), i);
1129 SetValueImpl (val, j);
1132 void double_swapper (int i, int j) {
1133 double[] array = this as double[];
1134 double val = array [i];
1135 array [i] = array [j];
1139 static int new_gap (int gap)
1141 gap = (gap * 10) / 13;
1142 if (gap == 9 || gap == 10)
1149 /* we use combsort because it's fast enough and very small, since we have
1150 * several specialized versions here.
1152 static void combsort (double[] array, int start, int size, Swapper swap_items)
1156 gap = new_gap (gap);
1157 bool swapped = false;
1158 int end = start + size - gap;
1159 for (int i = start; i < end; i++) {
1161 if (array [i] > array [j]) {
1162 double val = array [i];
1163 array [i] = array [j];
1166 if (swap_items != null)
1170 if (gap == 1 && !swapped)
1175 static void combsort (int[] array, int start, int size, Swapper swap_items)
1179 gap = new_gap (gap);
1180 bool swapped = false;
1181 int end = start + size - gap;
1182 for (int i = start; i < end; i++) {
1184 if (array [i] > array [j]) {
1185 int val = array [i];
1186 array [i] = array [j];
1189 if (swap_items != null)
1193 if (gap == 1 && !swapped)
1198 static void combsort (char[] array, int start, int size, Swapper swap_items)
1202 gap = new_gap (gap);
1203 bool swapped = false;
1204 int end = start + size - gap;
1205 for (int i = start; i < end; i++) {
1207 if (array [i] > array [j]) {
1208 char val = array [i];
1209 array [i] = array [j];
1212 if (swap_items != null)
1216 if (gap == 1 && !swapped)
1221 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1229 object objPivot = keys.GetValueImpl ((low + high) / 2);
1231 while (low <= high) {
1232 // Move the walls in
1233 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1235 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1239 swap (keys, items, low, high);
1246 qsort (keys, items, low0, high, comparer);
1248 qsort (keys, items, low, high0, comparer);
1251 private static void swap (Array keys, Array items, int i, int j)
1255 tmp = keys.GetValueImpl (i);
1256 keys.SetValueImpl (keys.GetValue (j), i);
1257 keys.SetValueImpl (tmp, j);
1259 if (items != null) {
1260 tmp = items.GetValueImpl (i);
1261 items.SetValueImpl (items.GetValueImpl (j), i);
1262 items.SetValueImpl (tmp, j);
1266 private static int compare (object value1, object value2, IComparer comparer)
1269 return value2 == null ? 0 : -1;
1270 else if (value2 == null)
1272 else if (comparer == null)
1273 return ((IComparable) value1).CompareTo (value2);
1275 return comparer.Compare (value1, value2);
1278 public virtual void CopyTo (Array array, int index)
1281 throw new ArgumentNullException ("array");
1283 // The order of these exception checks may look strange,
1284 // but that's how the microsoft runtime does it.
1286 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1287 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1288 throw new ArgumentException ();
1290 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1292 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1293 "Value has to be >= 0."));
1295 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1299 [ComVisible (false)]
1300 public virtual void CopyTo (Array array, long index)
1302 if (index < 0 || index > Int32.MaxValue)
1303 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1304 "Value must be >= 0 and <= Int32.MaxValue."));
1306 CopyTo (array, (int) index);
1310 internal class SimpleEnumerator : IEnumerator, ICloneable
1316 public SimpleEnumerator (Array arrayToEnumerate)
1318 this.enumeratee = arrayToEnumerate;
1319 this.currentpos = -1;
1320 this.length = arrayToEnumerate.Length;
1323 public object Current {
1325 // Exception messages based on MS implementation
1326 if (currentpos < 0 )
1327 throw new InvalidOperationException (Locale.GetText (
1328 "Enumeration has not started."));
1329 if (currentpos >= length)
1330 throw new InvalidOperationException (Locale.GetText (
1331 "Enumeration has already ended"));
1332 // Current should not increase the position. So no ++ over here.
1333 return enumeratee.GetValueImpl (currentpos);
1337 public bool MoveNext()
1339 //The docs say Current should throw an exception if last
1340 //call to MoveNext returned false. This means currentpos
1341 //should be set to length when returning false.
1342 if (currentpos < length)
1344 if(currentpos < length)
1355 public object Clone ()
1357 return MemberwiseClone ();
1362 public static void Resize <T> (ref T [] array, int newSize) {
1364 throw new ArgumentOutOfRangeException ();
1366 if (array == null) {
1367 array = new T [newSize];
1371 if (array.Length == newSize)
1374 T [] a = new T [newSize];
1375 Array.Copy (array, a, Math.Min (newSize, array.Length));
1379 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1382 throw new ArgumentNullException ("array");
1384 throw new ArgumentNullException ("match");
1386 foreach (T t in array)
1393 public static void ForEach<T> (T [] array, Action <T> action)
1396 throw new ArgumentNullException ("array");
1398 throw new ArgumentNullException ("action");
1400 foreach (T t in array)
1404 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1407 throw new ArgumentNullException ("array");
1408 if (converter == null)
1409 throw new ArgumentNullException ("converter");
1411 TOutput [] output = new TOutput [array.Length];
1412 for (int i = 0; i < array.Length; i ++)
1413 output [i] = converter (array [i]);
1418 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1421 throw new ArgumentNullException ("array");
1423 return FindLastIndex<T> (array, 0, array.Length, match);
1426 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1429 throw new ArgumentNullException ();
1431 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1434 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1437 throw new ArgumentNullException ("array");
1439 throw new ArgumentNullException ("match");
1441 if (startIndex > array.Length || startIndex + count > array.Length)
1442 throw new ArgumentOutOfRangeException ();
1444 for (int i = startIndex + count - 1; i >= startIndex; i--)
1445 if (match (array [i]))
1451 public static int FindIndex<T> (T [] array, Predicate<T> match)
1454 throw new ArgumentNullException ("array");
1456 return FindIndex<T> (array, 0, array.Length, match);
1459 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1462 throw new ArgumentNullException ("array");
1464 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1467 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1470 throw new ArgumentNullException ("array");
1473 throw new ArgumentNullException ("match");
1475 if (startIndex > array.Length || startIndex + count > array.Length)
1476 throw new ArgumentOutOfRangeException ();
1478 for (int i = startIndex; i < startIndex + count; i ++)
1479 if (match (array [i]))
1485 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1486 public static int BinarySearch<T> (T [] array, T value)
1489 throw new ArgumentNullException ("array");
1491 return BinarySearch<T> (array, 0, array.Length, value, null);
1494 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1495 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1498 throw new ArgumentNullException ("array");
1500 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1503 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1505 return BinarySearch<T> (array, offset, length, value, null);
1508 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1509 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1512 throw new ArgumentNullException ("array");
1514 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1515 "index is less than the lower bound of array."));
1517 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1518 "Value has to be >= 0."));
1519 // re-ordered to avoid possible integer overflow
1520 if (index > array.Length - length)
1521 throw new ArgumentException (Locale.GetText (
1522 "index and length do not specify a valid range in array."));
1523 if (comparer == null)
1524 comparer = Comparer <T>.Default;
1527 int iMax = index + length - 1;
1530 while (iMin <= iMax) {
1531 int iMid = (iMin + iMax) / 2;
1532 iCmp = comparer.Compare (value, array [iMid]);
1539 iMin = iMid + 1; // compensate for the rounding down
1541 } catch (Exception e) {
1542 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1548 public static int IndexOf<T> (T [] array, T value)
1551 throw new ArgumentNullException ("array");
1553 return IndexOf (array, value, 0, array.Length);
1556 public static int IndexOf<T> (T [] array, T value, int startIndex)
1559 throw new ArgumentNullException ("array");
1561 return IndexOf (array, value, startIndex, array.Length - startIndex);
1564 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
1567 throw new ArgumentNullException ("array");
1569 // re-ordered to avoid possible integer overflow
1570 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1571 throw new ArgumentOutOfRangeException ();
1573 int max = startIndex + count;
1574 for (int i = startIndex; i < max; i++) {
1575 if (Object.Equals (value, array [i]))
1582 public static int LastIndexOf<T> (T [] array, T value)
1585 throw new ArgumentNullException ("array");
1587 return LastIndexOf (array, value, array.Length - 1);
1590 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
1593 throw new ArgumentNullException ("array");
1595 return LastIndexOf (array, value, startIndex, startIndex + 1);
1598 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
1601 throw new ArgumentNullException ("array");
1603 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1604 throw new ArgumentOutOfRangeException ();
1606 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1607 if (Object.Equals (value, array [i]))
1614 public static T [] FindAll<T> (T [] array, Predicate <T> match)
1617 throw new ArgumentNullException ("array");
1620 throw new ArgumentNullException ("match");
1623 T [] d = new T [array.Length];
1624 foreach (T t in array)
1628 Resize <T> (ref d, pos);
1632 public static bool Exists<T> (T [] array, Predicate <T> match)
1635 throw new ArgumentNullException ("array");
1638 throw new ArgumentNullException ("match");
1640 foreach (T t in array)
1646 public static IList<T> AsReadOnly<T> (T[] array)
1649 throw new ArgumentNullException ("array");
1650 return new ReadOnlyArray<T> (array);
1653 public static Nullable<T> Find<T> (T [] array, Predicate<T> match)
1656 throw new ArgumentNullException ("array");
1659 throw new ArgumentNullException ("match");
1661 foreach (T t in array)
1663 return new Nullable <T> (t);
1665 return default (Nullable <T>);
1668 public static Nullable<T> FindLast<T> (T [] array, Predicate <T> match)
1671 throw new ArgumentNullException ("array");
1674 throw new ArgumentNullException ("match");
1676 for (int i = array.Length - 1; i >= 0; i--)
1677 if (match (array [i]))
1678 return new Nullable <T> (array [i]);
1680 return default (Nullable <T>);
1683 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
1685 // The constrained copy should guarantee that if there is an exception thrown
1686 // during the copy, the destination array remains unchanged.
1687 // This is related to System.Runtime.Reliability.CER
1688 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1690 Copy (s, s_i, d, d_i, c);
1696 // This is used internally by the runtime to represent arrays; see #74953.
1698 // Note that you normally can't derive a class from System.Array (CS0644),
1699 // but GMCS makes an exception here for all classes which are nested inside
1702 internal class InternalArray<T> : Array, IList<T>
1704 new public IEnumerator<T> GetEnumerator ()
1706 return new InternalEnumerator (this);
1715 bool ICollection<T>.IsReadOnly {
1721 void ICollection<T>.Clear ()
1723 throw new NotSupportedException ("Collection is read-only");
1726 void ICollection<T>.Add (T item)
1728 throw new NotSupportedException ("Collection is read-only");
1731 bool ICollection<T>.Remove (T item)
1733 throw new NotSupportedException ("Collection is read-only");
1736 public bool Contains (T item)
1739 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1741 int length = this.Length;
1742 for (int i = 0; i < length; i++) {
1744 GetGenericValueImpl (i, out value);
1745 if (item.Equals (value))
1752 public void CopyTo (T[] array, int index)
1755 throw new ArgumentNullException ("array");
1757 // The order of these exception checks may look strange,
1758 // but that's how the microsoft runtime does it.
1760 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1761 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1762 throw new ArgumentException ();
1764 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1766 throw new ArgumentOutOfRangeException (
1767 "index", Locale.GetText ("Value has to be >= 0."));
1769 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1772 new public T this [int index] {
1774 if (unchecked ((uint) index) >= unchecked ((uint) Length))
1775 throw new ArgumentOutOfRangeException ("index");
1778 GetGenericValueImpl (index, out value);
1783 throw new NotSupportedException ("Collection is read-only");
1787 void IList<T>.Insert (int index, T item)
1789 throw new NotSupportedException ("Collection is read-only");
1792 void IList<T>.RemoveAt (int index)
1794 throw new NotSupportedException ("Collection is read-only");
1797 public int IndexOf (T item)
1800 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1802 int length = this.Length;
1803 for (int i = 0; i < length; i++) {
1805 GetGenericValueImpl (i, out value);
1806 if (item.Equals (value))
1807 // array index may not be zero-based.
1809 return i + this.GetLowerBound (0);
1814 // lower bound may be MinValue
1815 retVal = this.GetLowerBound (0) - 1;
1821 // CAUTION! No bounds checking!
1822 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1823 protected extern void GetGenericValueImpl (int pos, out T value);
1825 internal struct InternalEnumerator : IEnumerator<T>
1827 const int NOT_STARTED = -2;
1829 // this MUST be -1, because we depend on it in move next.
1830 // we just decr the size, so, 0 - 1 == FINISHED
1831 const int FINISHED = -1;
1833 InternalArray<T> array;
1836 internal InternalEnumerator (InternalArray<T> array)
1842 public void Dispose ()
1847 public bool MoveNext ()
1849 if (idx == NOT_STARTED)
1852 return idx != FINISHED && -- idx != FINISHED;
1858 throw new InvalidOperationException ();
1860 return array [array.Length - 1 - idx];
1864 void IEnumerator.Reset ()
1866 throw new NotImplementedException ();
1869 object IEnumerator.Current {
1881 internal struct ReadOnlyArrayEnumerator <T> : IEnumerator <T> {
1882 const int NOT_STARTED = -2;
1884 // this MUST be -1, because we depend on it in move next.
1885 // we just decr the size, so, 0 - 1 == FINISHED
1886 const int FINISHED = -1;
1888 ReadOnlyArray <T> array;
1891 internal ReadOnlyArrayEnumerator (ReadOnlyArray<T> array)
1897 public void Dispose ()
1902 public bool MoveNext ()
1904 if (idx == NOT_STARTED)
1907 return idx != FINISHED && -- idx != FINISHED;
1913 throw new InvalidOperationException ();
1915 return array [array.Count - 1 - idx];
1919 void IEnumerator.Reset ()
1921 throw new NotImplementedException ();
1924 object IEnumerator.Current {
1931 internal class ReadOnlyArray <T> : ICollection <T>, IList <T>, IEnumerable <T>
1935 internal ReadOnlyArray (T[] array) {
1939 // ICollection<T> interface
1946 public bool IsReadOnly {
1952 public void Add (T item) {
1953 throw new NotSupportedException ("Collection is read-only");
1956 public bool Remove (T item) {
1957 throw new NotSupportedException ("Collection is read-only");
1960 public void Clear () {
1961 throw new NotSupportedException ("Collection is read-only");
1964 public void CopyTo (T[] array, int index) {
1965 arr.CopyTo (array, index);
1968 public bool Contains (T item) {
1969 return Array.IndexOf <T> (arr, item) != -1;
1972 // IList<T> interface
1973 public T this [int index] {
1975 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
1976 throw new ArgumentOutOfRangeException ("index");
1980 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
1981 throw new ArgumentOutOfRangeException ("index");
1982 arr [index] = value;
1986 public void Insert (int index, T item) {
1987 throw new NotSupportedException ("Collection is read-only");
1990 public void RemoveAt (int index) {
1991 throw new NotSupportedException ("Collection is read-only");
1994 public int IndexOf (T item) {
1995 return Array.IndexOf <T> (arr, item);
1998 // IEnumerable<T> interface
1999 public IEnumerator<T> GetEnumerator () {
2000 return new ReadOnlyArrayEnumerator <T> (this);
2003 IEnumerator IEnumerable.GetEnumerator () {
2004 return new ReadOnlyArrayEnumerator <T> (this);
2009 #if BOOTSTRAP_WITH_OLDLIB || NET_2_0
2010 /* delegate used to swap array elements, keep defined outside Array */
2011 delegate void Swapper (int i, int j);