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 (value1 is IComparable<T>)
1473 return ((IComparable<T>) value1).CompareTo (value2);
1474 else if (value1 is IComparable)
1475 return ((IComparable) value1).CompareTo (value2);
1476 else if (comparer != null)
1477 return comparer.Compare (value1, value2);
1479 string msg = Locale.GetText ("No IComparable or IComparable<T> interface found for type '{0}'.");
1480 throw new InvalidOperationException (String.Format (msg, typeof (T)));
1483 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1491 T keyPivot = array [(low + high) / 2];
1493 while (low <= high) {
1494 // Move the walls in
1495 while (low < high0 && comparison (array [low], keyPivot) < 0)
1497 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1501 swap<T> (array, low, high);
1508 qsort<T> (array, low0, high, comparison);
1510 qsort<T> (array, low, high0, comparison);
1513 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1518 keys [i] = keys [j];
1521 if (items != null) {
1524 items [i] = items [j];
1529 private static void swap<T> (T [] array, int i, int j)
1532 array [i] = array [j];
1537 public virtual void CopyTo (Array array, int index)
1540 throw new ArgumentNullException ("array");
1542 // The order of these exception checks may look strange,
1543 // but that's how the microsoft runtime does it.
1545 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1546 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1547 throw new ArgumentException ();
1549 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1551 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1552 "Value has to be >= 0."));
1554 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1558 [ComVisible (false)]
1559 public virtual void CopyTo (Array array, long index)
1561 if (index < 0 || index > Int32.MaxValue)
1562 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1563 "Value must be >= 0 and <= Int32.MaxValue."));
1565 CopyTo (array, (int) index);
1569 internal class SimpleEnumerator : IEnumerator, ICloneable
1575 public SimpleEnumerator (Array arrayToEnumerate)
1577 this.enumeratee = arrayToEnumerate;
1578 this.currentpos = -1;
1579 this.length = arrayToEnumerate.Length;
1582 public object Current {
1584 // Exception messages based on MS implementation
1585 if (currentpos < 0 )
1586 throw new InvalidOperationException (Locale.GetText (
1587 "Enumeration has not started."));
1588 if (currentpos >= length)
1589 throw new InvalidOperationException (Locale.GetText (
1590 "Enumeration has already ended"));
1591 // Current should not increase the position. So no ++ over here.
1592 return enumeratee.GetValueImpl (currentpos);
1596 public bool MoveNext()
1598 //The docs say Current should throw an exception if last
1599 //call to MoveNext returned false. This means currentpos
1600 //should be set to length when returning false.
1601 if (currentpos < length)
1603 if(currentpos < length)
1614 public object Clone ()
1616 return MemberwiseClone ();
1621 public static void Resize<T> (ref T [] array, int newSize)
1623 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1626 internal static void Resize<T> (ref T[] array, int length, int newSize)
1629 throw new ArgumentOutOfRangeException ();
1631 if (array == null) {
1632 array = new T [newSize];
1636 if (array.Length == newSize)
1639 T [] a = new T [newSize];
1640 Array.Copy (array, a, Math.Min (newSize, length));
1644 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1647 throw new ArgumentNullException ("array");
1649 throw new ArgumentNullException ("match");
1651 foreach (T t in array)
1658 public static void ForEach<T> (T [] array, Action <T> action)
1661 throw new ArgumentNullException ("array");
1663 throw new ArgumentNullException ("action");
1665 foreach (T t in array)
1669 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1672 throw new ArgumentNullException ("array");
1673 if (converter == null)
1674 throw new ArgumentNullException ("converter");
1676 TOutput [] output = new TOutput [array.Length];
1677 for (int i = 0; i < array.Length; i ++)
1678 output [i] = converter (array [i]);
1683 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1686 throw new ArgumentNullException ("array");
1688 return FindLastIndex<T> (array, 0, array.Length, match);
1691 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1694 throw new ArgumentNullException ();
1696 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1699 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1702 throw new ArgumentNullException ("array");
1704 throw new ArgumentNullException ("match");
1706 if (startIndex > array.Length || startIndex + count > array.Length)
1707 throw new ArgumentOutOfRangeException ();
1709 for (int i = startIndex + count - 1; i >= startIndex; i--)
1710 if (match (array [i]))
1716 public static int FindIndex<T> (T [] array, Predicate<T> match)
1719 throw new ArgumentNullException ("array");
1721 return FindIndex<T> (array, 0, array.Length, match);
1724 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1727 throw new ArgumentNullException ("array");
1729 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1732 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1735 throw new ArgumentNullException ("array");
1738 throw new ArgumentNullException ("match");
1740 if (startIndex > array.Length || startIndex + count > array.Length)
1741 throw new ArgumentOutOfRangeException ();
1743 for (int i = startIndex; i < startIndex + count; i ++)
1744 if (match (array [i]))
1750 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1751 public static int BinarySearch<T> (T [] array, T value)
1754 throw new ArgumentNullException ("array");
1756 return BinarySearch<T> (array, 0, array.Length, value, null);
1759 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1760 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1763 throw new ArgumentNullException ("array");
1765 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1768 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1770 return BinarySearch<T> (array, offset, length, value, null);
1773 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1774 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1777 throw new ArgumentNullException ("array");
1779 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1780 "index is less than the lower bound of array."));
1782 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1783 "Value has to be >= 0."));
1784 // re-ordered to avoid possible integer overflow
1785 if (index > array.Length - length)
1786 throw new ArgumentException (Locale.GetText (
1787 "index and length do not specify a valid range in array."));
1788 if (comparer == null)
1789 comparer = Comparer <T>.Default;
1792 int iMax = index + length - 1;
1795 while (iMin <= iMax) {
1796 int iMid = (iMin + iMax) / 2;
1797 iCmp = comparer.Compare (value, array [iMid]);
1804 iMin = iMid + 1; // compensate for the rounding down
1806 } catch (Exception e) {
1807 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1813 public static int IndexOf<T> (T [] array, T value)
1816 throw new ArgumentNullException ("array");
1818 return IndexOf (array, value, 0, array.Length);
1821 public static int IndexOf<T> (T [] array, T value, int startIndex)
1824 throw new ArgumentNullException ("array");
1826 return IndexOf (array, value, startIndex, array.Length - startIndex);
1829 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
1832 throw new ArgumentNullException ("array");
1834 // re-ordered to avoid possible integer overflow
1835 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1836 throw new ArgumentOutOfRangeException ();
1838 int max = startIndex + count;
1839 for (int i = startIndex; i < max; i++) {
1840 if (Object.Equals (value, array [i]))
1847 public static int LastIndexOf<T> (T [] array, T value)
1850 throw new ArgumentNullException ("array");
1852 return LastIndexOf (array, value, array.Length - 1);
1855 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
1858 throw new ArgumentNullException ("array");
1860 return LastIndexOf (array, value, startIndex, startIndex + 1);
1863 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
1866 throw new ArgumentNullException ("array");
1868 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1869 throw new ArgumentOutOfRangeException ();
1871 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1872 if (Object.Equals (value, array [i]))
1879 public static T [] FindAll<T> (T [] array, Predicate <T> match)
1882 throw new ArgumentNullException ("array");
1885 throw new ArgumentNullException ("match");
1888 T [] d = new T [array.Length];
1889 foreach (T t in array)
1893 Resize <T> (ref d, pos);
1897 public static bool Exists<T> (T [] array, Predicate <T> match)
1900 throw new ArgumentNullException ("array");
1903 throw new ArgumentNullException ("match");
1905 foreach (T t in array)
1911 public static IList<T> AsReadOnly<T> (T[] array)
1914 throw new ArgumentNullException ("array");
1915 return new ReadOnlyArray<T> (array);
1918 public static T Find<T> (T [] array, Predicate<T> match)
1921 throw new ArgumentNullException ("array");
1924 throw new ArgumentNullException ("match");
1926 foreach (T t in array)
1933 public static T FindLast<T> (T [] array, Predicate <T> match)
1936 throw new ArgumentNullException ("array");
1939 throw new ArgumentNullException ("match");
1941 for (int i = array.Length - 1; i >= 0; i--)
1942 if (match (array [i]))
1948 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
1950 // The constrained copy should guarantee that if there is an exception thrown
1951 // during the copy, the destination array remains unchanged.
1952 // This is related to System.Runtime.Reliability.CER
1953 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1955 Copy (s, s_i, d, d_i, c);
1961 // This is used internally by the runtime to represent arrays; see #74953.
1963 // Note that you normally can't derive a class from System.Array (CS0644),
1964 // but GMCS makes an exception here for all classes which are nested inside
1967 internal class InternalArray<T> : Array, IList<T>
1969 new public IEnumerator<T> GetEnumerator ()
1971 return new InternalEnumerator (this);
1980 bool ICollection<T>.IsReadOnly {
1986 void ICollection<T>.Clear ()
1988 throw new NotSupportedException ("Collection is read-only");
1991 void ICollection<T>.Add (T item)
1993 throw new NotSupportedException ("Collection is read-only");
1996 bool ICollection<T>.Remove (T item)
1998 throw new NotSupportedException ("Collection is read-only");
2001 public bool Contains (T item)
2004 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2006 int length = this.Length;
2007 for (int i = 0; i < length; i++) {
2009 GetGenericValueImpl (i, out value);
2010 if (item.Equals (value))
2017 public void CopyTo (T[] array, int index)
2020 throw new ArgumentNullException ("array");
2022 // The order of these exception checks may look strange,
2023 // but that's how the microsoft runtime does it.
2025 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2026 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
2027 throw new ArgumentException ();
2029 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2031 throw new ArgumentOutOfRangeException (
2032 "index", Locale.GetText ("Value has to be >= 0."));
2034 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
2037 new public T this [int index] {
2039 if (unchecked ((uint) index) >= unchecked ((uint) Length))
2040 throw new ArgumentOutOfRangeException ("index");
2043 GetGenericValueImpl (index, out value);
2048 throw new NotSupportedException ("Collection is read-only");
2052 void IList<T>.Insert (int index, T item)
2054 throw new NotSupportedException ("Collection is read-only");
2057 void IList<T>.RemoveAt (int index)
2059 throw new NotSupportedException ("Collection is read-only");
2062 public int IndexOf (T item)
2065 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2067 int length = this.Length;
2068 for (int i = 0; i < length; i++) {
2070 GetGenericValueImpl (i, out value);
2071 if (item.Equals (value))
2072 // array index may not be zero-based.
2074 return i + this.GetLowerBound (0);
2079 // lower bound may be MinValue
2080 retVal = this.GetLowerBound (0) - 1;
2086 // CAUTION! No bounds checking!
2087 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2088 protected extern void GetGenericValueImpl (int pos, out T value);
2090 internal struct InternalEnumerator : IEnumerator<T>
2092 const int NOT_STARTED = -2;
2094 // this MUST be -1, because we depend on it in move next.
2095 // we just decr the size, so, 0 - 1 == FINISHED
2096 const int FINISHED = -1;
2098 InternalArray<T> array;
2101 internal InternalEnumerator (InternalArray<T> array)
2107 public void Dispose ()
2112 public bool MoveNext ()
2114 if (idx == NOT_STARTED)
2117 return idx != FINISHED && -- idx != FINISHED;
2123 throw new InvalidOperationException ();
2125 return array [array.Length - 1 - idx];
2129 void IEnumerator.Reset ()
2131 throw new NotImplementedException ();
2134 object IEnumerator.Current {
2146 internal struct ReadOnlyArrayEnumerator <T> : IEnumerator <T> {
2147 const int NOT_STARTED = -2;
2149 // this MUST be -1, because we depend on it in move next.
2150 // we just decr the size, so, 0 - 1 == FINISHED
2151 const int FINISHED = -1;
2153 ReadOnlyArray <T> array;
2156 internal ReadOnlyArrayEnumerator (ReadOnlyArray<T> array)
2162 public void Dispose ()
2167 public bool MoveNext ()
2169 if (idx == NOT_STARTED)
2172 return idx != FINISHED && -- idx != FINISHED;
2178 throw new InvalidOperationException ();
2180 return array [array.Count - 1 - idx];
2184 void IEnumerator.Reset ()
2186 throw new NotImplementedException ();
2189 object IEnumerator.Current {
2196 internal class ReadOnlyArray <T> : ICollection <T>, IList <T>, IEnumerable <T>
2200 internal ReadOnlyArray (T[] array) {
2204 // ICollection<T> interface
2211 public bool IsReadOnly {
2217 public void Add (T item) {
2218 throw new NotSupportedException ("Collection is read-only");
2221 public bool Remove (T item) {
2222 throw new NotSupportedException ("Collection is read-only");
2225 public void Clear () {
2226 throw new NotSupportedException ("Collection is read-only");
2229 public void CopyTo (T[] array, int index) {
2230 arr.CopyTo (array, index);
2233 public bool Contains (T item) {
2234 return Array.IndexOf <T> (arr, item) != -1;
2237 // IList<T> interface
2238 public T this [int index] {
2240 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
2241 throw new ArgumentOutOfRangeException ("index");
2245 if (unchecked ((uint) index) >= unchecked ((uint) arr.Length))
2246 throw new ArgumentOutOfRangeException ("index");
2247 arr [index] = value;
2251 public void Insert (int index, T item) {
2252 throw new NotSupportedException ("Collection is read-only");
2255 public void RemoveAt (int index) {
2256 throw new NotSupportedException ("Collection is read-only");
2259 public int IndexOf (T item) {
2260 return Array.IndexOf <T> (arr, item);
2263 // IEnumerable<T> interface
2264 public IEnumerator<T> GetEnumerator () {
2265 return new ReadOnlyArrayEnumerator <T> (this);
2268 IEnumerator IEnumerable.GetEnumerator () {
2269 return new ReadOnlyArrayEnumerator <T> (this);
2274 #if BOOTSTRAP_WITH_OLDLIB
2275 /* delegate used to swap array elements, keep defined outside Array */
2276 delegate void Swapper (int i, int j);