5 // Joe Shaw (joe@ximian.com)
6 // Martin Baulig (martin@gnome.org)
7 // Dietmar Maurer (dietmar@ximian.com)
8 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
10 // (C) 2001-2003 Ximian, Inc. http://www.ximian.com
11 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
38 using System.Collections.Generic;
39 using System.Runtime.ConstrainedExecution;
46 [MonoTODO ("We are doing way to many double/triple exception checks for the overloaded functions")]
47 [MonoTODO ("Sort overloads parameter checks are VERY inconsistent")]
48 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
58 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
61 int length = this.GetLength (0);
63 for (int i = 1; i < this.Rank; i++) {
64 length *= this.GetLength (i);
72 public long LongLength {
74 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
76 get { return Length; }
82 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
85 return this.GetRank ();
90 object IList.this [int index] {
92 if (unchecked ((uint) index) >= unchecked ((uint) Length))
93 throw new ArgumentOutOfRangeException ("index");
94 return GetValueImpl (index);
97 if (unchecked ((uint) index) >= unchecked ((uint) Length))
98 throw new ArgumentOutOfRangeException ("index");
99 SetValueImpl (value, index);
103 int IList.Add (object value)
105 throw new NotSupportedException ();
110 Array.Clear (this, this.GetLowerBound (0), this.Length);
113 bool IList.Contains (object value)
116 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
118 int length = this.Length;
119 for (int i = 0; i < length; i++) {
120 if (Object.Equals (value, this.GetValueImpl (i)))
127 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
129 int IList.IndexOf (object value)
132 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
134 int length = this.Length;
135 for (int i = 0; i < length; i++) {
136 if (Object.Equals (value, this.GetValueImpl (i)))
137 // array index may not be zero-based.
139 return i + this.GetLowerBound (0);
144 // lower bound may be MinValue
145 retVal = this.GetLowerBound (0) - 1;
151 void IList.Insert (int index, object value)
153 throw new NotSupportedException ();
156 void IList.Remove (object value)
158 throw new NotSupportedException ();
161 void IList.RemoveAt (int index)
163 throw new NotSupportedException ();
166 // InternalCall Methods
167 [MethodImplAttribute (MethodImplOptions.InternalCall)]
168 private extern int GetRank ();
170 [MethodImplAttribute (MethodImplOptions.InternalCall)]
171 public extern int GetLength (int dimension);
175 public long GetLongLength (int dimension)
177 return GetLength (dimension);
182 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
184 [MethodImplAttribute (MethodImplOptions.InternalCall)]
185 public extern int GetLowerBound (int dimension);
187 [MethodImplAttribute (MethodImplOptions.InternalCall)]
188 public extern object GetValue (params int[] indices);
190 [MethodImplAttribute (MethodImplOptions.InternalCall)]
191 public extern void SetValue (object value, params int[] indices);
193 // CAUTION! No bounds checking!
194 [MethodImplAttribute (MethodImplOptions.InternalCall)]
195 internal extern object GetValueImpl (int pos);
197 // CAUTION! No bounds checking!
198 [MethodImplAttribute (MethodImplOptions.InternalCall)]
199 internal extern void SetValueImpl (object value, int pos);
201 [MethodImplAttribute (MethodImplOptions.InternalCall)]
202 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
204 [MethodImplAttribute (MethodImplOptions.InternalCall)]
205 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
208 int ICollection.Count {
214 public virtual bool IsSynchronized {
220 public virtual object SyncRoot {
226 public virtual bool IsFixedSize {
232 public virtual bool IsReadOnly {
238 public virtual IEnumerator GetEnumerator ()
240 return new SimpleEnumerator (this);
244 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
246 public int GetUpperBound (int dimension)
248 return GetLowerBound (dimension) + GetLength (dimension) - 1;
251 public object GetValue (int index)
254 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
255 if (index < GetLowerBound (0) || index > GetUpperBound (0))
256 throw new IndexOutOfRangeException (Locale.GetText (
257 "Index has to be between upper and lower bound of the array."));
259 return GetValueImpl (index - GetLowerBound (0));
262 public object GetValue (int index1, int index2)
264 int[] ind = {index1, index2};
265 return GetValue (ind);
268 public object GetValue (int index1, int index2, int index3)
270 int[] ind = {index1, index2, index3};
271 return GetValue (ind);
276 public object GetValue (long index)
278 if (index < 0 || index > Int32.MaxValue)
279 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
280 "Value must be >= 0 and <= Int32.MaxValue."));
282 return GetValue ((int) index);
286 public object GetValue (long index1, long index2)
288 if (index1 < 0 || index1 > Int32.MaxValue)
289 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
290 "Value must be >= 0 and <= Int32.MaxValue."));
292 if (index2 < 0 || index2 > Int32.MaxValue)
293 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
294 "Value must be >= 0 and <= Int32.MaxValue."));
296 return GetValue ((int) index1, (int) index2);
300 public object GetValue (long index1, long index2, long index3)
302 if (index1 < 0 || index1 > Int32.MaxValue)
303 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
304 "Value must be >= 0 and <= Int32.MaxValue."));
306 if (index2 < 0 || index2 > Int32.MaxValue)
307 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
308 "Value must be >= 0 and <= Int32.MaxValue."));
310 if (index3 < 0 || index3 > Int32.MaxValue)
311 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
312 "Value must be >= 0 and <= Int32.MaxValue."));
314 return GetValue ((int) index1, (int) index2, (int) index3);
318 public void SetValue (object value, long index)
320 if (index < 0 || index > Int32.MaxValue)
321 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
322 "Value must be >= 0 and <= Int32.MaxValue."));
324 SetValue (value, (int) index);
328 public void SetValue (object value, long index1, long index2)
330 if (index1 < 0 || index1 > Int32.MaxValue)
331 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
332 "Value must be >= 0 and <= Int32.MaxValue."));
334 if (index2 < 0 || index2 > Int32.MaxValue)
335 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
336 "Value must be >= 0 and <= Int32.MaxValue."));
338 int[] ind = {(int) index1, (int) index2};
339 SetValue (value, ind);
343 public void SetValue (object value, long index1, long index2, long index3)
345 if (index1 < 0 || index1 > Int32.MaxValue)
346 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
347 "Value must be >= 0 and <= Int32.MaxValue."));
349 if (index2 < 0 || index2 > Int32.MaxValue)
350 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
351 "Value must be >= 0 and <= Int32.MaxValue."));
353 if (index3 < 0 || index3 > Int32.MaxValue)
354 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
355 "Value must be >= 0 and <= Int32.MaxValue."));
357 int[] ind = {(int) index1, (int) index2, (int) index3};
358 SetValue (value, ind);
362 public void SetValue (object value, int index)
365 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
366 if (index < GetLowerBound (0) || index > GetUpperBound (0))
367 throw new IndexOutOfRangeException (Locale.GetText (
368 "Index has to be >= lower bound and <= upper bound of the array."));
370 SetValueImpl (value, index - GetLowerBound (0));
373 public void SetValue (object value, int index1, int index2)
375 int[] ind = {index1, index2};
376 SetValue (value, ind);
379 public void SetValue (object value, int index1, int index2, int index3)
381 int[] ind = {index1, index2, index3};
382 SetValue (value, ind);
385 public static Array CreateInstance (Type elementType, int length)
387 int[] lengths = {length};
389 return CreateInstance (elementType, lengths);
392 public static Array CreateInstance (Type elementType, int length1, int length2)
394 int[] lengths = {length1, length2};
396 return CreateInstance (elementType, lengths);
399 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
401 int[] lengths = {length1, length2, length3};
403 return CreateInstance (elementType, lengths);
406 public static Array CreateInstance (Type elementType, int[] lengths)
408 if (elementType == null)
409 throw new ArgumentNullException ("elementType");
411 throw new ArgumentNullException ("lengths");
413 if (lengths.Length > 255)
414 throw new TypeLoadException ();
418 elementType = elementType.UnderlyingSystemType;
419 if (!elementType.IsSystemType)
420 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
422 return CreateInstanceImpl (elementType, lengths, bounds);
425 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
427 if (elementType == null)
428 throw new ArgumentNullException ("elementType");
430 throw new ArgumentNullException ("lengths");
432 throw new ArgumentNullException ("bounds");
434 elementType = elementType.UnderlyingSystemType;
435 if (!elementType.IsSystemType)
436 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
438 if (lengths.Length < 1)
439 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
441 if (lengths.Length != bounds.Length)
442 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
444 for (int j = 0; j < bounds.Length; j ++) {
446 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
447 "Each value has to be >= 0."));
448 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
449 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
450 "Length + bound must not exceed Int32.MaxValue."));
453 if (lengths.Length > 255)
454 throw new TypeLoadException ();
456 return CreateInstanceImpl (elementType, lengths, bounds);
460 static int [] GetIntArray (long [] values)
462 int len = values.Length;
463 int [] ints = new int [len];
464 for (int i = 0; i < len; i++) {
465 long current = values [i];
466 if (current < 0 || current > (long) Int32.MaxValue)
467 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
468 "Each value has to be >= 0 and <= Int32.MaxValue."));
470 ints [i] = (int) current;
475 public static Array CreateInstance (Type elementType, params long [] lengths)
479 throw new ArgumentNullException ("lengths");
481 return CreateInstance (elementType, GetIntArray (lengths));
485 public object GetValue (params long [] indices)
489 throw new ArgumentNullException ("indices");
491 return GetValue (GetIntArray (indices));
495 public void SetValue (object value, params long [] indices)
499 throw new ArgumentNullException ("indices");
501 SetValue (value, GetIntArray (indices));
506 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
508 public static int BinarySearch (Array array, object value)
511 throw new ArgumentNullException ("array");
517 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
519 if (array.Length == 0)
522 if (!(value is IComparable))
523 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
525 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
529 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
531 public static int BinarySearch (Array array, object value, IComparer comparer)
534 throw new ArgumentNullException ("array");
537 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
539 if (array.Length == 0)
542 if ((comparer == null) && (value != null) && !(value is IComparable))
543 throw new ArgumentException (Locale.GetText (
544 "comparer is null and value does not support IComparable."));
546 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
550 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
552 public static int BinarySearch (Array array, int index, int length, object value)
555 throw new ArgumentNullException ("array");
558 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
560 if (index < array.GetLowerBound (0))
561 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
562 "index is less than the lower bound of array."));
564 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
565 "Value has to be >= 0."));
566 // re-ordered to avoid possible integer overflow
567 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
568 throw new ArgumentException (Locale.GetText (
569 "index and length do not specify a valid range in array."));
571 if (array.Length == 0)
574 if ((value != null) && (!(value is IComparable)))
575 throw new ArgumentException (Locale.GetText (
576 "value does not support IComparable"));
578 return DoBinarySearch (array, index, length, value, null);
582 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
584 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
587 throw new ArgumentNullException ("array");
590 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
592 if (index < array.GetLowerBound (0))
593 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
594 "index is less than the lower bound of array."));
596 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
597 "Value has to be >= 0."));
598 // re-ordered to avoid possible integer overflow
599 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
600 throw new ArgumentException (Locale.GetText (
601 "index and length do not specify a valid range in array."));
603 if (array.Length == 0)
606 if ((comparer == null) && (value != null) && !(value is IComparable))
607 throw new ArgumentException (Locale.GetText (
608 "comparer is null and value does not support IComparable."));
610 return DoBinarySearch (array, index, length, value, comparer);
613 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
615 // cache this in case we need it
616 if (comparer == null)
617 comparer = Comparer.Default;
620 // Comment from Tum (tum@veridicus.com):
621 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
622 int iMax = index + length - 1;
625 while (iMin <= iMax) {
626 int iMid = (iMin + iMax) / 2;
627 object elt = array.GetValueImpl (iMid);
629 iCmp = comparer.Compare (elt, value);
636 iMin = iMid + 1; // compensate for the rounding down
639 catch (Exception e) {
640 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
647 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
649 public static void Clear (Array array, int index, int length)
652 throw new ArgumentNullException ("array");
654 throw new ArgumentOutOfRangeException ("length < 0");
656 int low = array.GetLowerBound (0);
658 throw new IndexOutOfRangeException ("index < lower bound");
661 // re-ordered to avoid possible integer overflow
662 if (index > array.Length - length)
663 throw new IndexOutOfRangeException ("index + length > size");
665 ClearInternal (array, index, length);
668 [MethodImplAttribute (MethodImplOptions.InternalCall)]
669 static extern void ClearInternal (Array a, int index, int count);
671 [MethodImplAttribute (MethodImplOptions.InternalCall)]
672 public virtual extern object Clone ();
675 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
677 public static void Copy (Array sourceArray, Array destinationArray, int length)
679 // need these checks here because we are going to use
680 // GetLowerBound() on source and dest.
681 if (sourceArray == null)
682 throw new ArgumentNullException ("sourceArray");
684 if (destinationArray == null)
685 throw new ArgumentNullException ("destinationArray");
687 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
688 destinationArray.GetLowerBound (0), length);
692 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
694 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
696 if (sourceArray == null)
697 throw new ArgumentNullException ("sourceArray");
699 if (destinationArray == null)
700 throw new ArgumentNullException ("destinationArray");
703 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
704 "Value has to be >= 0."));;
707 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
708 "Value has to be >= 0."));;
710 if (destinationIndex < 0)
711 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
712 "Value has to be >= 0."));;
714 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
717 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
718 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
720 // re-ordered to avoid possible integer overflow
721 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
722 throw new ArgumentException ("length");
724 if (sourceArray.Rank != destinationArray.Rank)
725 throw new RankException (Locale.GetText ("Arrays must be of same size."));
727 Type src_type = sourceArray.GetType ().GetElementType ();
728 Type dst_type = destinationArray.GetType ().GetElementType ();
730 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
731 for (int i = 0; i < length; i++) {
732 Object srcval = sourceArray.GetValueImpl (source_pos + i);
735 destinationArray.SetValueImpl (srcval, dest_pos + i);
737 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
738 (src_type.Equals (typeof (Object))))
739 throw new InvalidCastException ();
741 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
742 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
747 for (int i = length - 1; i >= 0; i--) {
748 Object srcval = sourceArray.GetValueImpl (source_pos + i);
751 destinationArray.SetValueImpl (srcval, dest_pos + i);
753 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
754 (src_type.Equals (typeof (Object))))
755 throw new InvalidCastException ();
757 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
758 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
766 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
768 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
769 long destinationIndex, long length)
771 if (sourceArray == null)
772 throw new ArgumentNullException ("sourceArray");
774 if (destinationArray == null)
775 throw new ArgumentNullException ("destinationArray");
777 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
778 throw new ArgumentOutOfRangeException ("sourceIndex",
779 Locale.GetText ("Must be in the Int32 range."));
781 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
782 throw new ArgumentOutOfRangeException ("destinationIndex",
783 Locale.GetText ("Must be in the Int32 range."));
785 if (length < 0 || length > Int32.MaxValue)
786 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
787 "Value must be >= 0 and <= Int32.MaxValue."));
789 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
793 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
795 public static void Copy (Array sourceArray, Array destinationArray, long length)
797 if (length < 0 || length > Int32.MaxValue)
798 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
799 "Value must be >= 0 and <= Int32.MaxValue."));
801 Copy (sourceArray, destinationArray, (int) length);
806 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
808 public static int IndexOf (Array array, object value)
811 throw new ArgumentNullException ("array");
813 return IndexOf (array, value, 0, array.Length);
817 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
819 public static int IndexOf (Array array, object value, int startIndex)
822 throw new ArgumentNullException ("array");
824 return IndexOf (array, value, startIndex, array.Length - startIndex);
828 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
830 public static int IndexOf (Array array, object value, int startIndex, int count)
833 throw new ArgumentNullException ("array");
836 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
838 // re-ordered to avoid possible integer overflow
839 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
840 throw new ArgumentOutOfRangeException ();
842 int max = startIndex + count;
843 for (int i = startIndex; i < max; i++) {
844 if (Object.Equals (value, array.GetValueImpl (i)))
848 return array.GetLowerBound (0) - 1;
852 public void Initialize()
854 //FIXME: We would like to find a compiler that uses
855 // this method. It looks like this method do nothing
856 // in C# so no exception is trown by the moment.
860 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
862 public static int LastIndexOf (Array array, object value)
865 throw new ArgumentNullException ("array");
867 return LastIndexOf (array, value, array.Length - 1);
871 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
873 public static int LastIndexOf (Array array, object value, int startIndex)
876 throw new ArgumentNullException ("array");
878 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
882 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
884 public static int LastIndexOf (Array array, object value, int startIndex, int count)
887 throw new ArgumentNullException ("array");
890 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
892 if (count < 0 || startIndex < array.GetLowerBound (0) ||
893 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
894 throw new ArgumentOutOfRangeException ();
896 for (int i = startIndex; i >= startIndex - count + 1; i--) {
897 if (Object.Equals (value, array.GetValueImpl (i)))
901 return array.GetLowerBound (0) - 1;
904 #if !BOOTSTRAP_WITH_OLDLIB
905 /* delegate used to swap array elements */
906 delegate void Swapper (int i, int j);
909 static Swapper get_swapper (Array array)
912 return new Swapper (array.int_swapper);
913 if (array is double[])
914 return new Swapper (array.double_swapper);
915 if (array is object[]) {
916 return new Swapper (array.obj_swapper);
918 return new Swapper (array.slow_swapper);
922 static Swapper get_swapper<T> (T [] array)
925 return new Swapper (array.int_swapper);
926 if (array is double[])
927 return new Swapper (array.double_swapper);
929 return new Swapper (array.obj_swapper);
934 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
936 public static void Reverse (Array array)
939 throw new ArgumentNullException ("array");
941 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
945 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
947 public static void Reverse (Array array, int index, int length)
950 throw new ArgumentNullException ("array");
953 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
955 if (index < array.GetLowerBound (0) || length < 0)
956 throw new ArgumentOutOfRangeException ();
958 // re-ordered to avoid possible integer overflow
959 if (index > array.GetUpperBound (0) + 1 - length)
960 throw new ArgumentException ();
962 int end = index + length - 1;
963 object[] oarray = array as object[];
964 if (oarray != null) {
965 while (index < end) {
966 object tmp = oarray [index];
967 oarray [index] = oarray [end];
974 int[] iarray = array as int[];
975 if (iarray != null) {
976 while (index < end) {
977 int tmp = iarray [index];
978 iarray [index] = iarray [end];
985 double[] darray = array as double[];
986 if (darray != null) {
987 while (index < end) {
988 double tmp = darray [index];
989 darray [index] = darray [end];
997 Swapper swapper = get_swapper (array);
998 while (index < end) {
999 swapper (index, end);
1006 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1008 public static void Sort (Array array)
1011 throw new ArgumentNullException ("array");
1013 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
1017 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1019 public static void Sort (Array keys, Array items)
1022 throw new ArgumentNullException ("keys");
1024 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1028 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1030 public static void Sort (Array array, IComparer comparer)
1033 throw new ArgumentNullException ("array");
1035 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1039 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1041 public static void Sort (Array array, int index, int length)
1043 Sort (array, null, index, length, null);
1047 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1049 public static void Sort (Array keys, Array items, IComparer comparer)
1052 throw new ArgumentNullException ("keys");
1054 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1058 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1060 public static void Sort (Array keys, Array items, int index, int length)
1062 Sort (keys, items, index, length, null);
1066 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1068 public static void Sort (Array array, int index, int length, IComparer comparer)
1070 Sort (array, null, index, length, comparer);
1074 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1077 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1080 throw new ArgumentNullException ("keys");
1082 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1083 throw new RankException ();
1085 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1086 throw new ArgumentException ();
1088 if (index < keys.GetLowerBound (0))
1089 throw new ArgumentOutOfRangeException ("index");
1092 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1093 "Value has to be >= 0."));
1095 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1096 throw new ArgumentException ();
1101 if (comparer == null) {
1106 iswapper = get_swapper (items);
1107 if (keys is double[]) {
1108 combsort (keys as double[], index, length, iswapper);
1111 if (keys is int[]) {
1112 combsort (keys as int[], index, length, iswapper);
1115 if (keys is char[]) {
1116 combsort (keys as char[], index, length, iswapper);
1122 int high0 = index + length - 1;
1123 qsort (keys, items, low0, high0, comparer);
1125 catch (Exception e) {
1126 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1130 /* note, these are instance methods */
1131 void int_swapper (int i, int j) {
1132 int[] array = this as int[];
1133 int val = array [i];
1134 array [i] = array [j];
1138 void obj_swapper (int i, int j) {
1139 object[] array = this as object[];
1140 object val = array [i];
1141 array [i] = array [j];
1145 void slow_swapper (int i, int j) {
1146 object val = GetValueImpl (i);
1147 SetValueImpl (GetValue (j), i);
1148 SetValueImpl (val, j);
1151 void double_swapper (int i, int j) {
1152 double[] array = this as double[];
1153 double val = array [i];
1154 array [i] = array [j];
1158 static int new_gap (int gap)
1160 gap = (gap * 10) / 13;
1161 if (gap == 9 || gap == 10)
1168 /* we use combsort because it's fast enough and very small, since we have
1169 * several specialized versions here.
1171 static void combsort (double[] array, int start, int size, Swapper swap_items)
1175 gap = new_gap (gap);
1176 bool swapped = false;
1177 int end = start + size - gap;
1178 for (int i = start; i < end; i++) {
1180 if (array [i] > array [j]) {
1181 double val = array [i];
1182 array [i] = array [j];
1185 if (swap_items != null)
1189 if (gap == 1 && !swapped)
1194 static void combsort (int[] array, int start, int size, Swapper swap_items)
1198 gap = new_gap (gap);
1199 bool swapped = false;
1200 int end = start + size - gap;
1201 for (int i = start; i < end; i++) {
1203 if (array [i] > array [j]) {
1204 int val = array [i];
1205 array [i] = array [j];
1208 if (swap_items != null)
1212 if (gap == 1 && !swapped)
1217 static void combsort (char[] array, int start, int size, Swapper swap_items)
1221 gap = new_gap (gap);
1222 bool swapped = false;
1223 int end = start + size - gap;
1224 for (int i = start; i < end; i++) {
1226 if (array [i] > array [j]) {
1227 char val = array [i];
1228 array [i] = array [j];
1231 if (swap_items != null)
1235 if (gap == 1 && !swapped)
1240 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1248 object objPivot = keys.GetValueImpl ((low + high) / 2);
1250 while (low <= high) {
1251 // Move the walls in
1252 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1254 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1258 swap (keys, items, low, high);
1265 qsort (keys, items, low0, high, comparer);
1267 qsort (keys, items, low, high0, comparer);
1270 private static void swap (Array keys, Array items, int i, int j)
1274 tmp = keys.GetValueImpl (i);
1275 keys.SetValueImpl (keys.GetValue (j), i);
1276 keys.SetValueImpl (tmp, j);
1278 if (items != null) {
1279 tmp = items.GetValueImpl (i);
1280 items.SetValueImpl (items.GetValueImpl (j), i);
1281 items.SetValueImpl (tmp, j);
1285 private static int compare (object value1, object value2, IComparer comparer)
1288 return value2 == null ? 0 : -1;
1289 else if (value2 == null)
1291 else if (comparer == null)
1292 return ((IComparable) value1).CompareTo (value2);
1294 return comparer.Compare (value1, value2);
1298 [CLSCompliant (false)]
1299 public static void Sort<T> (T [] array)
1302 throw new ArgumentNullException ("array");
1304 Sort<T, T> (array, null, 0, array.Length, null);
1307 [CLSCompliant (false)]
1308 public static void Sort<K, V> (K [] keys, V [] items)
1311 throw new ArgumentNullException ("keys");
1313 Sort<K, V> (keys, items, 0, keys.Length, null);
1316 [CLSCompliant (false)]
1317 public static void Sort<T> (T [] array, IComparer<T> comparer)
1320 throw new ArgumentNullException ("array");
1322 Sort<T, T> (array, null, 0, array.Length, comparer);
1325 [CLSCompliant (false)]
1326 public static void Sort<K, V> (K [] keys, V [] items, IComparer<K> comparer)
1329 throw new ArgumentNullException ("keys");
1331 Sort<K, V> (keys, items, 0, keys.Length, comparer);
1334 [CLSCompliant (false)]
1335 public static void Sort<T> (T [] array, int index, int length)
1338 throw new ArgumentNullException ("array");
1340 Sort<T, T> (array, null, index, length, null);
1343 [CLSCompliant (false)]
1344 public static void Sort<K, V> (K [] keys, V [] items, int index, int length)
1346 Sort<K, V> (keys, items, index, length, null);
1349 [CLSCompliant (false)]
1350 public static void Sort<T> (T [] array, int index, int length, IComparer<T> comparer)
1353 throw new ArgumentNullException ("array");
1355 Sort<T, T> (array, null, index, length, comparer);
1358 [CLSCompliant (false)]
1359 public static void Sort<K, V> (K [] keys, V [] items, int index, int length, IComparer<K> comparer)
1362 throw new ArgumentNullException ("keys");
1365 throw new ArgumentOutOfRangeException ("index");
1368 throw new ArgumentOutOfRangeException ("length");
1370 if (keys.Length - index < length
1371 || (items != null && index > items.Length - length))
1372 throw new ArgumentException ();
1378 // Check for value types which can be sorted without Compare () method
1380 if (comparer == null) {
1385 iswapper = get_swapper<V> (items);
1386 if (keys is double[]) {
1387 combsort (keys as double[], index, length, iswapper);
1390 if (keys is int[]) {
1391 combsort (keys as int[], index, length, iswapper);
1394 if (keys is char[]) {
1395 combsort (keys as char[], index, length, iswapper);
1399 // Use Comparer<T>.Default instead
1400 // comparer = Comparer<K>.Default;
1405 int high0 = index + length - 1;
1406 qsort<K, V> (keys, items, low0, high0, comparer);
1408 catch (Exception e) {
1409 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1413 [CLSCompliant (false)]
1414 public static void Sort<T> (T [] array, Comparison<T> comparison)
1417 throw new ArgumentNullException ("array");
1418 if (comparison == null)
1419 throw new ArgumentNullException ("comparison");
1421 if (array.Length <= 1)
1426 int high0 = array.Length - 1;
1427 qsort<T> (array, low0, high0, comparison);
1429 catch (Exception e) {
1430 throw new InvalidOperationException (Locale.GetText ("Comparison threw an exception."), e);
1434 private static void qsort<K, V> (K [] keys, V [] items, int low0, int high0, IComparer<K> comparer)
1442 K keyPivot = keys [(low + high) / 2];
1444 while (low <= high) {
1445 // Move the walls in
1446 //while (low < high0 && comparer.Compare (keys [low], keyPivot) < 0)
1447 while (low < high0 && compare (keys [low], keyPivot, comparer) < 0)
1449 //while (high > low0 && comparer.Compare (keyPivot, keys [high]) < 0)
1450 while (high > low0 && compare (keyPivot, keys [high], comparer) < 0)
1454 swap<K, V> (keys, items, low, high);
1461 qsort<K, V> (keys, items, low0, high, comparer);
1463 qsort<K, V> (keys, items, low, high0, comparer);
1466 private static int compare<T> (T value1, T value2, IComparer<T> comparer)
1469 return value2 == null ? 0 : -1;
1470 else if (value2 == null)
1472 else if (comparer == null)
1473 if (value1 is IComparable<T>)
1474 return ((IComparable<T>) value1).CompareTo (value2);
1476 return ((IComparable) value1).CompareTo (value2);
1478 return comparer.Compare (value1, value2);
1481 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1489 T keyPivot = array [(low + high) / 2];
1491 while (low <= high) {
1492 // Move the walls in
1493 while (low < high0 && comparison (array [low], keyPivot) < 0)
1495 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1499 swap<T> (array, low, high);
1506 qsort<T> (array, low0, high, comparison);
1508 qsort<T> (array, low, high0, comparison);
1511 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1516 keys [i] = keys [j];
1519 if (items != null) {
1522 items [i] = items [j];
1527 private static void swap<T> (T [] array, int i, int j)
1530 array [i] = array [j];
1535 public virtual void CopyTo (Array array, int index)
1538 throw new ArgumentNullException ("array");
1540 // The order of these exception checks may look strange,
1541 // but that's how the microsoft runtime does it.
1543 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1544 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1545 throw new ArgumentException ();
1547 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1549 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1550 "Value has to be >= 0."));
1552 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1556 [ComVisible (false)]
1557 public virtual void CopyTo (Array array, long index)
1559 if (index < 0 || index > Int32.MaxValue)
1560 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1561 "Value must be >= 0 and <= Int32.MaxValue."));
1563 CopyTo (array, (int) index);
1567 internal class SimpleEnumerator : IEnumerator, ICloneable
1573 public SimpleEnumerator (Array arrayToEnumerate)
1575 this.enumeratee = arrayToEnumerate;
1576 this.currentpos = -1;
1577 this.length = arrayToEnumerate.Length;
1580 public object Current {
1582 // Exception messages based on MS implementation
1583 if (currentpos < 0 )
1584 throw new InvalidOperationException (Locale.GetText (
1585 "Enumeration has not started."));
1586 if (currentpos >= length)
1587 throw new InvalidOperationException (Locale.GetText (
1588 "Enumeration has already ended"));
1589 // Current should not increase the position. So no ++ over here.
1590 return enumeratee.GetValueImpl (currentpos);
1594 public bool MoveNext()
1596 //The docs say Current should throw an exception if last
1597 //call to MoveNext returned false. This means currentpos
1598 //should be set to length when returning false.
1599 if (currentpos < length)
1601 if(currentpos < length)
1612 public object Clone ()
1614 return MemberwiseClone ();
1619 public static void Resize<T> (ref T [] array, int newSize)
1621 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1624 internal static void Resize<T> (ref T[] array, int length, int newSize)
1627 throw new ArgumentOutOfRangeException ();
1629 if (array == null) {
1630 array = new T [newSize];
1634 if (array.Length == newSize)
1637 T [] a = new T [newSize];
1638 Array.Copy (array, a, Math.Min (newSize, length));
1642 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1645 throw new ArgumentNullException ("array");
1647 throw new ArgumentNullException ("match");
1649 foreach (T t in array)
1656 public static void ForEach<T> (T [] array, Action <T> action)
1659 throw new ArgumentNullException ("array");
1661 throw new ArgumentNullException ("action");
1663 foreach (T t in array)
1667 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1670 throw new ArgumentNullException ("array");
1671 if (converter == null)
1672 throw new ArgumentNullException ("converter");
1674 TOutput [] output = new TOutput [array.Length];
1675 for (int i = 0; i < array.Length; i ++)
1676 output [i] = converter (array [i]);
1681 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1684 throw new ArgumentNullException ("array");
1686 return FindLastIndex<T> (array, 0, array.Length, match);
1689 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1692 throw new ArgumentNullException ();
1694 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1697 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1700 throw new ArgumentNullException ("array");
1702 throw new ArgumentNullException ("match");
1704 if (startIndex > array.Length || startIndex + count > array.Length)
1705 throw new ArgumentOutOfRangeException ();
1707 for (int i = startIndex + count - 1; i >= startIndex; i--)
1708 if (match (array [i]))
1714 public static int FindIndex<T> (T [] array, Predicate<T> match)
1717 throw new ArgumentNullException ("array");
1719 return FindIndex<T> (array, 0, array.Length, match);
1722 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1725 throw new ArgumentNullException ("array");
1727 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1730 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1733 throw new ArgumentNullException ("array");
1736 throw new ArgumentNullException ("match");
1738 if (startIndex > array.Length || startIndex + count > array.Length)
1739 throw new ArgumentOutOfRangeException ();
1741 for (int i = startIndex; i < startIndex + count; i ++)
1742 if (match (array [i]))
1748 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1749 public static int BinarySearch<T> (T [] array, T value)
1752 throw new ArgumentNullException ("array");
1754 return BinarySearch<T> (array, 0, array.Length, value, null);
1757 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1758 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1761 throw new ArgumentNullException ("array");
1763 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1766 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1768 return BinarySearch<T> (array, offset, length, value, null);
1771 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1772 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1775 throw new ArgumentNullException ("array");
1777 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1778 "index is less than the lower bound of array."));
1780 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1781 "Value has to be >= 0."));
1782 // re-ordered to avoid possible integer overflow
1783 if (index > array.Length - length)
1784 throw new ArgumentException (Locale.GetText (
1785 "index and length do not specify a valid range in array."));
1786 if (comparer == null)
1787 comparer = Comparer <T>.Default;
1790 int iMax = index + length - 1;
1793 while (iMin <= iMax) {
1794 int iMid = (iMin + iMax) / 2;
1795 iCmp = comparer.Compare (value, array [iMid]);
1802 iMin = iMid + 1; // compensate for the rounding down
1804 } catch (Exception e) {
1805 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1811 public static int IndexOf<T> (T [] array, T value)
1814 throw new ArgumentNullException ("array");
1816 return IndexOf (array, value, 0, array.Length);
1819 public static int IndexOf<T> (T [] array, T value, int startIndex)
1822 throw new ArgumentNullException ("array");
1824 return IndexOf (array, value, startIndex, array.Length - startIndex);
1827 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
1830 throw new ArgumentNullException ("array");
1832 // re-ordered to avoid possible integer overflow
1833 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1834 throw new ArgumentOutOfRangeException ();
1836 int max = startIndex + count;
1837 for (int i = startIndex; i < max; i++) {
1838 if (Object.Equals (value, array [i]))
1845 public static int LastIndexOf<T> (T [] array, T value)
1848 throw new ArgumentNullException ("array");
1850 return LastIndexOf (array, value, array.Length - 1);
1853 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
1856 throw new ArgumentNullException ("array");
1858 return LastIndexOf (array, value, startIndex, startIndex + 1);
1861 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
1864 throw new ArgumentNullException ("array");
1866 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1867 throw new ArgumentOutOfRangeException ();
1869 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1870 if (Object.Equals (value, array [i]))
1877 public static T [] FindAll<T> (T [] array, Predicate <T> match)
1880 throw new ArgumentNullException ("array");
1883 throw new ArgumentNullException ("match");
1886 T [] d = new T [array.Length];
1887 foreach (T t in array)
1891 Resize <T> (ref d, pos);
1895 public static bool Exists<T> (T [] array, Predicate <T> match)
1898 throw new ArgumentNullException ("array");
1901 throw new ArgumentNullException ("match");
1903 foreach (T t in array)
1909 public static IList<T> AsReadOnly<T> (T[] array)
1912 throw new ArgumentNullException ("array");
1913 return new ReadOnlyArray<T> (array);
1916 public static Nullable<T> Find<T> (T [] array, Predicate<T> match)
1919 throw new ArgumentNullException ("array");
1922 throw new ArgumentNullException ("match");
1924 foreach (T t in array)
1926 return new Nullable <T> (t);
1928 return default (Nullable <T>);
1931 public static Nullable<T> FindLast<T> (T [] array, Predicate <T> match)
1934 throw new ArgumentNullException ("array");
1937 throw new ArgumentNullException ("match");
1939 for (int i = array.Length - 1; i >= 0; i--)
1940 if (match (array [i]))
1941 return new Nullable <T> (array [i]);
1943 return default (Nullable <T>);
1946 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
1948 // The constrained copy should guarantee that if there is an exception thrown
1949 // during the copy, the destination array remains unchanged.
1950 // This is related to System.Runtime.Reliability.CER
1951 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1953 Copy (s, s_i, d, d_i, c);
1959 // This is used internally by the runtime to represent arrays; see #74953.
1961 // Note that you normally can't derive a class from System.Array (CS0644),
1962 // but GMCS makes an exception here for all classes which are nested inside
1965 internal class InternalArray<T> : Array, IList<T>
1967 new public IEnumerator<T> GetEnumerator ()
1969 return new InternalEnumerator (this);
1978 bool ICollection<T>.IsReadOnly {
1984 void ICollection<T>.Clear ()
1986 throw new NotSupportedException ("Collection is read-only");
1989 void ICollection<T>.Add (T item)
1991 throw new NotSupportedException ("Collection is read-only");
1994 bool ICollection<T>.Remove (T item)
1996 throw new NotSupportedException ("Collection is read-only");
1999 public bool Contains (T item)
2002 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2004 int length = this.Length;
2005 for (int i = 0; i < length; i++) {
2007 GetGenericValueImpl (i, out value);
2008 if (item.Equals (value))
2015 public void CopyTo (T[] array, int index)
2018 throw new ArgumentNullException ("array");
2020 // The order of these exception checks may look strange,
2021 // but that's how the microsoft runtime does it.
2023 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2024 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
2025 throw new ArgumentException ();
2027 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2029 throw new ArgumentOutOfRangeException (
2030 "index", Locale.GetText ("Value has to be >= 0."));
2032 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
2035 new public T this [int index] {
2037 if (unchecked ((uint) index) >= unchecked ((uint) Length))
2038 throw new ArgumentOutOfRangeException ("index");
2041 GetGenericValueImpl (index, out value);
2046 throw new NotSupportedException ("Collection is read-only");
2050 void IList<T>.Insert (int index, T item)
2052 throw new NotSupportedException ("Collection is read-only");
2055 void IList<T>.RemoveAt (int index)
2057 throw new NotSupportedException ("Collection is read-only");
2060 public int IndexOf (T item)
2063 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2065 int length = this.Length;
2066 for (int i = 0; i < length; i++) {
2068 GetGenericValueImpl (i, out value);
2069 if (item.Equals (value))
2070 // array index may not be zero-based.
2072 return i + this.GetLowerBound (0);
2077 // lower bound may be MinValue
2078 retVal = this.GetLowerBound (0) - 1;
2084 // CAUTION! No bounds checking!
2085 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2086 protected extern void GetGenericValueImpl (int pos, out T value);
2088 internal struct InternalEnumerator : IEnumerator<T>
2090 const int NOT_STARTED = -2;
2092 // this MUST be -1, because we depend on it in move next.
2093 // we just decr the size, so, 0 - 1 == FINISHED
2094 const int FINISHED = -1;
2096 InternalArray<T> array;
2099 internal InternalEnumerator (InternalArray<T> array)
2105 public void Dispose ()
2110 public bool MoveNext ()
2112 if (idx == NOT_STARTED)
2115 return idx != FINISHED && -- idx != FINISHED;
2121 throw new InvalidOperationException ();
2123 return array [array.Length - 1 - idx];
2127 void IEnumerator.Reset ()
2129 throw new NotImplementedException ();
2132 object IEnumerator.Current {
2144 internal struct ReadOnlyArrayEnumerator <T> : IEnumerator <T> {
2145 const int NOT_STARTED = -2;
2147 // this MUST be -1, because we depend on it in move next.
2148 // we just decr the size, so, 0 - 1 == FINISHED
2149 const int FINISHED = -1;
2151 ReadOnlyArray <T> array;
2154 internal ReadOnlyArrayEnumerator (ReadOnlyArray<T> array)
2160 public void Dispose ()
2165 public bool MoveNext ()
2167 if (idx == NOT_STARTED)
2170 return idx != FINISHED && -- idx != FINISHED;
2176 throw new InvalidOperationException ();
2178 return array [array.Count - 1 - idx];
2182 void IEnumerator.Reset ()
2184 throw new NotImplementedException ();
2187 object IEnumerator.Current {
2194 internal class ReadOnlyArray <T> : ICollection <T>, IList <T>, IEnumerable <T>
2198 internal ReadOnlyArray (T[] array) {
2202 // ICollection<T> interface
2209 public bool IsReadOnly {
2215 public void Add (T item) {
2216 throw new NotSupportedException ("Collection is read-only");
2219 public bool Remove (T item) {
2220 throw new NotSupportedException ("Collection is read-only");
2223 public void Clear () {
2224 throw new NotSupportedException ("Collection is read-only");
2227 public void CopyTo (T[] array, int index) {
2228 arr.CopyTo (array, index);
2231 public bool Contains (T item) {
2232 return Array.IndexOf <T> (arr, item) != -1;
2235 // IList<T> interface
2236 public T this [int index] {
2238 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
2239 throw new ArgumentOutOfRangeException ("index");
2243 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
2244 throw new ArgumentOutOfRangeException ("index");
2245 arr [index] = value;
2249 public void Insert (int index, T item) {
2250 throw new NotSupportedException ("Collection is read-only");
2253 public void RemoveAt (int index) {
2254 throw new NotSupportedException ("Collection is read-only");
2257 public int IndexOf (T item) {
2258 return Array.IndexOf <T> (arr, item);
2261 // IEnumerable<T> interface
2262 public IEnumerator<T> GetEnumerator () {
2263 return new ReadOnlyArrayEnumerator <T> (this);
2266 IEnumerator IEnumerable.GetEnumerator () {
2267 return new ReadOnlyArrayEnumerator <T> (this);
2272 #if BOOTSTRAP_WITH_OLDLIB
2273 /* delegate used to swap array elements, keep defined outside Array */
2274 delegate void Swapper (int i, int j);