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 (params int[] indices);
193 [MethodImplAttribute (MethodImplOptions.InternalCall)]
194 public extern void SetValue (object value, params 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 (params 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, params 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
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 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1367 internal static void Resize<T> (ref T[] array, int length, int newSize)
1370 throw new ArgumentOutOfRangeException ();
1372 if (array == null) {
1373 array = new T [newSize];
1377 if (array.Length == newSize)
1380 T [] a = new T [newSize];
1381 Array.Copy (array, a, Math.Min (newSize, length));
1385 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1388 throw new ArgumentNullException ("array");
1390 throw new ArgumentNullException ("match");
1392 foreach (T t in array)
1399 public static void ForEach<T> (T [] array, Action <T> action)
1402 throw new ArgumentNullException ("array");
1404 throw new ArgumentNullException ("action");
1406 foreach (T t in array)
1410 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1413 throw new ArgumentNullException ("array");
1414 if (converter == null)
1415 throw new ArgumentNullException ("converter");
1417 TOutput [] output = new TOutput [array.Length];
1418 for (int i = 0; i < array.Length; i ++)
1419 output [i] = converter (array [i]);
1424 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1427 throw new ArgumentNullException ("array");
1429 return FindLastIndex<T> (array, 0, array.Length, match);
1432 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1435 throw new ArgumentNullException ();
1437 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1440 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1443 throw new ArgumentNullException ("array");
1445 throw new ArgumentNullException ("match");
1447 if (startIndex > array.Length || startIndex + count > array.Length)
1448 throw new ArgumentOutOfRangeException ();
1450 for (int i = startIndex + count - 1; i >= startIndex; i--)
1451 if (match (array [i]))
1457 public static int FindIndex<T> (T [] array, Predicate<T> match)
1460 throw new ArgumentNullException ("array");
1462 return FindIndex<T> (array, 0, array.Length, match);
1465 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1468 throw new ArgumentNullException ("array");
1470 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1473 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1476 throw new ArgumentNullException ("array");
1479 throw new ArgumentNullException ("match");
1481 if (startIndex > array.Length || startIndex + count > array.Length)
1482 throw new ArgumentOutOfRangeException ();
1484 for (int i = startIndex; i < startIndex + count; i ++)
1485 if (match (array [i]))
1491 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1492 public static int BinarySearch<T> (T [] array, T value)
1495 throw new ArgumentNullException ("array");
1497 return BinarySearch<T> (array, 0, array.Length, value, null);
1500 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1501 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1504 throw new ArgumentNullException ("array");
1506 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1509 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1511 return BinarySearch<T> (array, offset, length, value, null);
1514 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1515 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1518 throw new ArgumentNullException ("array");
1520 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1521 "index is less than the lower bound of array."));
1523 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1524 "Value has to be >= 0."));
1525 // re-ordered to avoid possible integer overflow
1526 if (index > array.Length - length)
1527 throw new ArgumentException (Locale.GetText (
1528 "index and length do not specify a valid range in array."));
1529 if (comparer == null)
1530 comparer = Comparer <T>.Default;
1533 int iMax = index + length - 1;
1536 while (iMin <= iMax) {
1537 int iMid = (iMin + iMax) / 2;
1538 iCmp = comparer.Compare (value, array [iMid]);
1545 iMin = iMid + 1; // compensate for the rounding down
1547 } catch (Exception e) {
1548 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1554 public static int IndexOf<T> (T [] array, T value)
1557 throw new ArgumentNullException ("array");
1559 return IndexOf (array, value, 0, array.Length);
1562 public static int IndexOf<T> (T [] array, T value, int startIndex)
1565 throw new ArgumentNullException ("array");
1567 return IndexOf (array, value, startIndex, array.Length - startIndex);
1570 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
1573 throw new ArgumentNullException ("array");
1575 // re-ordered to avoid possible integer overflow
1576 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1577 throw new ArgumentOutOfRangeException ();
1579 int max = startIndex + count;
1580 for (int i = startIndex; i < max; i++) {
1581 if (Object.Equals (value, array [i]))
1588 public static int LastIndexOf<T> (T [] array, T value)
1591 throw new ArgumentNullException ("array");
1593 return LastIndexOf (array, value, array.Length - 1);
1596 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
1599 throw new ArgumentNullException ("array");
1601 return LastIndexOf (array, value, startIndex, startIndex + 1);
1604 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
1607 throw new ArgumentNullException ("array");
1609 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1610 throw new ArgumentOutOfRangeException ();
1612 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1613 if (Object.Equals (value, array [i]))
1620 public static T [] FindAll<T> (T [] array, Predicate <T> match)
1623 throw new ArgumentNullException ("array");
1626 throw new ArgumentNullException ("match");
1629 T [] d = new T [array.Length];
1630 foreach (T t in array)
1634 Resize <T> (ref d, pos);
1638 public static bool Exists<T> (T [] array, Predicate <T> match)
1641 throw new ArgumentNullException ("array");
1644 throw new ArgumentNullException ("match");
1646 foreach (T t in array)
1652 public static IList<T> AsReadOnly<T> (T[] array)
1655 throw new ArgumentNullException ("array");
1656 return new ReadOnlyArray<T> (array);
1659 public static Nullable<T> Find<T> (T [] array, Predicate<T> match)
1662 throw new ArgumentNullException ("array");
1665 throw new ArgumentNullException ("match");
1667 foreach (T t in array)
1669 return new Nullable <T> (t);
1671 return default (Nullable <T>);
1674 public static Nullable<T> FindLast<T> (T [] array, Predicate <T> match)
1677 throw new ArgumentNullException ("array");
1680 throw new ArgumentNullException ("match");
1682 for (int i = array.Length - 1; i >= 0; i--)
1683 if (match (array [i]))
1684 return new Nullable <T> (array [i]);
1686 return default (Nullable <T>);
1689 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
1691 // The constrained copy should guarantee that if there is an exception thrown
1692 // during the copy, the destination array remains unchanged.
1693 // This is related to System.Runtime.Reliability.CER
1694 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1696 Copy (s, s_i, d, d_i, c);
1702 // This is used internally by the runtime to represent arrays; see #74953.
1704 // Note that you normally can't derive a class from System.Array (CS0644),
1705 // but GMCS makes an exception here for all classes which are nested inside
1708 internal class InternalArray<T> : Array, IList<T>
1710 new public IEnumerator<T> GetEnumerator ()
1712 return new InternalEnumerator (this);
1721 bool ICollection<T>.IsReadOnly {
1727 void ICollection<T>.Clear ()
1729 throw new NotSupportedException ("Collection is read-only");
1732 void ICollection<T>.Add (T item)
1734 throw new NotSupportedException ("Collection is read-only");
1737 bool ICollection<T>.Remove (T item)
1739 throw new NotSupportedException ("Collection is read-only");
1742 public bool Contains (T item)
1745 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1747 int length = this.Length;
1748 for (int i = 0; i < length; i++) {
1750 GetGenericValueImpl (i, out value);
1751 if (item.Equals (value))
1758 public void CopyTo (T[] array, int index)
1761 throw new ArgumentNullException ("array");
1763 // The order of these exception checks may look strange,
1764 // but that's how the microsoft runtime does it.
1766 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1767 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1768 throw new ArgumentException ();
1770 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1772 throw new ArgumentOutOfRangeException (
1773 "index", Locale.GetText ("Value has to be >= 0."));
1775 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1778 new public T this [int index] {
1780 if (unchecked ((uint) index) >= unchecked ((uint) Length))
1781 throw new ArgumentOutOfRangeException ("index");
1784 GetGenericValueImpl (index, out value);
1789 throw new NotSupportedException ("Collection is read-only");
1793 void IList<T>.Insert (int index, T item)
1795 throw new NotSupportedException ("Collection is read-only");
1798 void IList<T>.RemoveAt (int index)
1800 throw new NotSupportedException ("Collection is read-only");
1803 public int IndexOf (T item)
1806 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1808 int length = this.Length;
1809 for (int i = 0; i < length; i++) {
1811 GetGenericValueImpl (i, out value);
1812 if (item.Equals (value))
1813 // array index may not be zero-based.
1815 return i + this.GetLowerBound (0);
1820 // lower bound may be MinValue
1821 retVal = this.GetLowerBound (0) - 1;
1827 // CAUTION! No bounds checking!
1828 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1829 protected extern void GetGenericValueImpl (int pos, out T value);
1831 internal struct InternalEnumerator : IEnumerator<T>
1833 const int NOT_STARTED = -2;
1835 // this MUST be -1, because we depend on it in move next.
1836 // we just decr the size, so, 0 - 1 == FINISHED
1837 const int FINISHED = -1;
1839 InternalArray<T> array;
1842 internal InternalEnumerator (InternalArray<T> array)
1848 public void Dispose ()
1853 public bool MoveNext ()
1855 if (idx == NOT_STARTED)
1858 return idx != FINISHED && -- idx != FINISHED;
1864 throw new InvalidOperationException ();
1866 return array [array.Length - 1 - idx];
1870 void IEnumerator.Reset ()
1872 throw new NotImplementedException ();
1875 object IEnumerator.Current {
1887 internal struct ReadOnlyArrayEnumerator <T> : IEnumerator <T> {
1888 const int NOT_STARTED = -2;
1890 // this MUST be -1, because we depend on it in move next.
1891 // we just decr the size, so, 0 - 1 == FINISHED
1892 const int FINISHED = -1;
1894 ReadOnlyArray <T> array;
1897 internal ReadOnlyArrayEnumerator (ReadOnlyArray<T> array)
1903 public void Dispose ()
1908 public bool MoveNext ()
1910 if (idx == NOT_STARTED)
1913 return idx != FINISHED && -- idx != FINISHED;
1919 throw new InvalidOperationException ();
1921 return array [array.Count - 1 - idx];
1925 void IEnumerator.Reset ()
1927 throw new NotImplementedException ();
1930 object IEnumerator.Current {
1937 internal class ReadOnlyArray <T> : ICollection <T>, IList <T>, IEnumerable <T>
1941 internal ReadOnlyArray (T[] array) {
1945 // ICollection<T> interface
1952 public bool IsReadOnly {
1958 public void Add (T item) {
1959 throw new NotSupportedException ("Collection is read-only");
1962 public bool Remove (T item) {
1963 throw new NotSupportedException ("Collection is read-only");
1966 public void Clear () {
1967 throw new NotSupportedException ("Collection is read-only");
1970 public void CopyTo (T[] array, int index) {
1971 arr.CopyTo (array, index);
1974 public bool Contains (T item) {
1975 return Array.IndexOf <T> (arr, item) != -1;
1978 // IList<T> interface
1979 public T this [int index] {
1981 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
1982 throw new ArgumentOutOfRangeException ("index");
1986 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
1987 throw new ArgumentOutOfRangeException ("index");
1988 arr [index] = value;
1992 public void Insert (int index, T item) {
1993 throw new NotSupportedException ("Collection is read-only");
1996 public void RemoveAt (int index) {
1997 throw new NotSupportedException ("Collection is read-only");
2000 public int IndexOf (T item) {
2001 return Array.IndexOf <T> (arr, item);
2004 // IEnumerable<T> interface
2005 public IEnumerator<T> GetEnumerator () {
2006 return new ReadOnlyArrayEnumerator <T> (this);
2009 IEnumerator IEnumerable.GetEnumerator () {
2010 return new ReadOnlyArrayEnumerator <T> (this);
2015 #if BOOTSTRAP_WITH_OLDLIB
2016 /* delegate used to swap array elements, keep defined outside Array */
2017 delegate void Swapper (int i, int j);