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.Collections.ObjectModel;
40 using System.Runtime.ConstrainedExecution;
49 // FIXME: We are doing way to many double/triple exception checks for the overloaded functions"
50 // FIXME: Sort overloads parameter checks are VERY inconsistent"
51 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
60 * These methods are used to implement the implicit generic interfaces
61 * implemented by arrays in NET 2.0.
62 * Only make those methods generic which really need it, to avoid
63 * creating useless instantiations.
65 internal int InternalArray__ICollection_get_Count ()
70 internal bool InternalArray__ICollection_get_IsReadOnly ()
75 internal IEnumerator<T> InternalArray__IEnumerable_GetEnumerator<T> ()
77 return new InternalEnumerator<T> (this);
80 internal void InternalArray__ICollection_Clear ()
82 throw new NotSupportedException ("Collection is read-only");
85 internal void InternalArray__ICollection_Add<T> (T item)
87 throw new NotSupportedException ("Collection is read-only");
90 internal bool InternalArray__ICollection_Remove<T> (T item)
92 throw new NotSupportedException ("Collection is read-only");
95 internal bool InternalArray__ICollection_Contains<T> (T item)
98 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
100 int length = this.Length;
101 for (int i = 0; i < length; i++) {
103 GetGenericValueImpl (i, out value);
111 if (item.Equals (value))
118 internal void InternalArray__ICollection_CopyTo<T> (T[] array, int index)
121 throw new ArgumentNullException ("array");
123 // The order of these exception checks may look strange,
124 // but that's how the microsoft runtime does it.
126 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
127 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
128 throw new ArgumentException ("Destination array was not long " +
129 "enough. Check destIndex and length, and the array's " +
132 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
134 throw new ArgumentOutOfRangeException (
135 "index", Locale.GetText ("Value has to be >= 0."));
137 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
140 internal void InternalArray__Insert<T> (int index, T item)
142 throw new NotSupportedException ("Collection is read-only");
145 internal void InternalArray__RemoveAt (int index)
147 throw new NotSupportedException ("Collection is read-only");
150 internal int InternalArray__IndexOf<T> (T item)
153 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
155 int length = this.Length;
156 for (int i = 0; i < length; i++) {
158 GetGenericValueImpl (i, out value);
161 return i + this.GetLowerBound (0);
164 return this.GetLowerBound (0) - 1;
168 if (value.Equals (item))
169 // array index may not be zero-based.
171 return i + this.GetLowerBound (0);
175 // lower bound may be MinValue
176 return this.GetLowerBound (0) - 1;
180 internal T InternalArray__get_Item<T> (int index)
182 if (unchecked ((uint) index) >= unchecked ((uint) Length))
183 throw new ArgumentOutOfRangeException ("index");
186 GetGenericValueImpl (index, out value);
190 internal void InternalArray__set_Item<T> (int index, T item)
192 if (unchecked ((uint) index) >= unchecked ((uint) Length))
193 throw new ArgumentOutOfRangeException ("index");
195 object[] oarray = this as object [];
196 if (oarray != null) {
197 oarray [index] = (object)item;
200 SetGenericValueImpl (index, ref item);
203 // CAUTION! No bounds checking!
204 [MethodImplAttribute (MethodImplOptions.InternalCall)]
205 internal extern void GetGenericValueImpl<T> (int pos, out T value);
207 // CAUTION! No bounds checking!
208 [MethodImplAttribute (MethodImplOptions.InternalCall)]
209 internal extern void SetGenericValueImpl<T> (int pos, ref T value);
211 internal struct InternalEnumerator<T> : IEnumerator<T>
213 const int NOT_STARTED = -2;
215 // this MUST be -1, because we depend on it in move next.
216 // we just decr the size, so, 0 - 1 == FINISHED
217 const int FINISHED = -1;
222 internal InternalEnumerator (Array array)
228 public void Dispose ()
233 public bool MoveNext ()
235 if (idx == NOT_STARTED)
238 return idx != FINISHED && -- idx != FINISHED;
243 if (idx == NOT_STARTED)
244 throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
246 throw new InvalidOperationException ("Enumeration already finished");
248 return array.InternalArray__get_Item<T> (array.Length - 1 - idx);
252 void IEnumerator.Reset ()
257 object IEnumerator.Current {
268 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
271 int length = this.GetLength (0);
273 for (int i = 1; i < this.Rank; i++) {
274 length *= this.GetLength (i);
282 public long LongLength {
284 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
286 get { return Length; }
292 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
295 return this.GetRank ();
300 object IList.this [int index] {
302 if (unchecked ((uint) index) >= unchecked ((uint) Length))
303 throw new ArgumentOutOfRangeException ("index");
304 return GetValueImpl (index);
307 if (unchecked ((uint) index) >= unchecked ((uint) Length))
308 throw new ArgumentOutOfRangeException ("index");
309 SetValueImpl (value, index);
313 int IList.Add (object value)
315 throw new NotSupportedException ();
320 Array.Clear (this, this.GetLowerBound (0), this.Length);
323 bool IList.Contains (object value)
326 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
328 int length = this.Length;
329 for (int i = 0; i < length; i++) {
330 if (Object.Equals (this.GetValueImpl (i), value))
337 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
339 int IList.IndexOf (object value)
342 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
344 int length = this.Length;
345 for (int i = 0; i < length; i++) {
346 if (Object.Equals (this.GetValueImpl (i), value))
347 // array index may not be zero-based.
349 return i + this.GetLowerBound (0);
353 // lower bound may be MinValue
354 return this.GetLowerBound (0) - 1;
358 void IList.Insert (int index, object value)
360 throw new NotSupportedException ();
363 void IList.Remove (object value)
365 throw new NotSupportedException ();
368 void IList.RemoveAt (int index)
370 throw new NotSupportedException ();
373 // InternalCall Methods
374 [MethodImplAttribute (MethodImplOptions.InternalCall)]
375 extern int GetRank ();
377 [MethodImplAttribute (MethodImplOptions.InternalCall)]
378 public extern int GetLength (int dimension);
382 public long GetLongLength (int dimension)
384 return GetLength (dimension);
389 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
391 [MethodImplAttribute (MethodImplOptions.InternalCall)]
392 public extern int GetLowerBound (int dimension);
394 [MethodImplAttribute (MethodImplOptions.InternalCall)]
395 public extern object GetValue (params int[] indices);
397 [MethodImplAttribute (MethodImplOptions.InternalCall)]
398 public extern void SetValue (object value, params int[] indices);
400 // CAUTION! No bounds checking!
401 [MethodImplAttribute (MethodImplOptions.InternalCall)]
402 internal extern object GetValueImpl (int pos);
404 // CAUTION! No bounds checking!
405 [MethodImplAttribute (MethodImplOptions.InternalCall)]
406 internal extern void SetValueImpl (object value, int pos);
408 [MethodImplAttribute (MethodImplOptions.InternalCall)]
409 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
411 [MethodImplAttribute (MethodImplOptions.InternalCall)]
412 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
415 int ICollection.Count {
425 bool IsSynchronized {
465 IEnumerator GetEnumerator ()
467 return new SimpleEnumerator (this);
471 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
473 public int GetUpperBound (int dimension)
475 return GetLowerBound (dimension) + GetLength (dimension) - 1;
478 public object GetValue (int index)
481 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
482 if (index < GetLowerBound (0) || index > GetUpperBound (0))
483 throw new IndexOutOfRangeException (Locale.GetText (
484 "Index has to be between upper and lower bound of the array."));
486 return GetValueImpl (index - GetLowerBound (0));
489 public object GetValue (int index1, int index2)
491 int[] ind = {index1, index2};
492 return GetValue (ind);
495 public object GetValue (int index1, int index2, int index3)
497 int[] ind = {index1, index2, index3};
498 return GetValue (ind);
503 public object GetValue (long index)
505 if (index < 0 || index > Int32.MaxValue)
506 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
507 "Value must be >= 0 and <= Int32.MaxValue."));
509 return GetValue ((int) index);
513 public object GetValue (long index1, long index2)
515 if (index1 < 0 || index1 > Int32.MaxValue)
516 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
517 "Value must be >= 0 and <= Int32.MaxValue."));
519 if (index2 < 0 || index2 > Int32.MaxValue)
520 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
521 "Value must be >= 0 and <= Int32.MaxValue."));
523 return GetValue ((int) index1, (int) index2);
527 public object GetValue (long index1, long index2, long index3)
529 if (index1 < 0 || index1 > Int32.MaxValue)
530 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
531 "Value must be >= 0 and <= Int32.MaxValue."));
533 if (index2 < 0 || index2 > Int32.MaxValue)
534 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
535 "Value must be >= 0 and <= Int32.MaxValue."));
537 if (index3 < 0 || index3 > Int32.MaxValue)
538 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
539 "Value must be >= 0 and <= Int32.MaxValue."));
541 return GetValue ((int) index1, (int) index2, (int) index3);
545 public void SetValue (object value, long index)
547 if (index < 0 || index > Int32.MaxValue)
548 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
549 "Value must be >= 0 and <= Int32.MaxValue."));
551 SetValue (value, (int) index);
555 public void SetValue (object value, long index1, long index2)
557 if (index1 < 0 || index1 > Int32.MaxValue)
558 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
559 "Value must be >= 0 and <= Int32.MaxValue."));
561 if (index2 < 0 || index2 > Int32.MaxValue)
562 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
563 "Value must be >= 0 and <= Int32.MaxValue."));
565 int[] ind = {(int) index1, (int) index2};
566 SetValue (value, ind);
570 public void SetValue (object value, long index1, long index2, long index3)
572 if (index1 < 0 || index1 > Int32.MaxValue)
573 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
574 "Value must be >= 0 and <= Int32.MaxValue."));
576 if (index2 < 0 || index2 > Int32.MaxValue)
577 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
578 "Value must be >= 0 and <= Int32.MaxValue."));
580 if (index3 < 0 || index3 > Int32.MaxValue)
581 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
582 "Value must be >= 0 and <= Int32.MaxValue."));
584 int[] ind = {(int) index1, (int) index2, (int) index3};
585 SetValue (value, ind);
589 public void SetValue (object value, int index)
592 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
593 if (index < GetLowerBound (0) || index > GetUpperBound (0))
594 throw new IndexOutOfRangeException (Locale.GetText (
595 "Index has to be >= lower bound and <= upper bound of the array."));
597 SetValueImpl (value, index - GetLowerBound (0));
600 public void SetValue (object value, int index1, int index2)
602 int[] ind = {index1, index2};
603 SetValue (value, ind);
606 public void SetValue (object value, int index1, int index2, int index3)
608 int[] ind = {index1, index2, index3};
609 SetValue (value, ind);
612 public static Array CreateInstance (Type elementType, int length)
614 int[] lengths = {length};
616 return CreateInstance (elementType, lengths);
619 public static Array CreateInstance (Type elementType, int length1, int length2)
621 int[] lengths = {length1, length2};
623 return CreateInstance (elementType, lengths);
626 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
628 int[] lengths = {length1, length2, length3};
630 return CreateInstance (elementType, lengths);
633 public static Array CreateInstance (Type elementType, params int[] lengths)
635 if (elementType == null)
636 throw new ArgumentNullException ("elementType");
638 throw new ArgumentNullException ("lengths");
640 if (lengths.Length > 255)
641 throw new TypeLoadException ();
645 elementType = elementType.UnderlyingSystemType;
646 if (!elementType.IsSystemType)
647 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
649 return CreateInstanceImpl (elementType, lengths, bounds);
652 public static Array CreateInstance (Type elementType, int[] lengths, int [] lowerBounds)
654 if (elementType == null)
655 throw new ArgumentNullException ("elementType");
657 throw new ArgumentNullException ("lengths");
658 if (lowerBounds == null)
659 throw new ArgumentNullException ("lowerBounds");
661 elementType = elementType.UnderlyingSystemType;
662 if (!elementType.IsSystemType)
663 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
665 if (lengths.Length < 1)
666 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
668 if (lengths.Length != lowerBounds.Length)
669 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
671 for (int j = 0; j < lowerBounds.Length; j ++) {
673 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
674 "Each value has to be >= 0."));
675 if ((long)lowerBounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
676 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
677 "Length + bound must not exceed Int32.MaxValue."));
680 if (lengths.Length > 255)
681 throw new TypeLoadException ();
683 return CreateInstanceImpl (elementType, lengths, lowerBounds);
687 static int [] GetIntArray (long [] values)
689 int len = values.Length;
690 int [] ints = new int [len];
691 for (int i = 0; i < len; i++) {
692 long current = values [i];
693 if (current < 0 || current > (long) Int32.MaxValue)
694 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
695 "Each value has to be >= 0 and <= Int32.MaxValue."));
697 ints [i] = (int) current;
702 public static Array CreateInstance (Type elementType, params long [] lengths)
706 throw new ArgumentNullException ("lengths");
708 return CreateInstance (elementType, GetIntArray (lengths));
712 public object GetValue (params long [] indices)
716 throw new ArgumentNullException ("indices");
718 return GetValue (GetIntArray (indices));
722 public void SetValue (object value, params long [] indices)
726 throw new ArgumentNullException ("indices");
728 SetValue (value, GetIntArray (indices));
733 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
735 public static int BinarySearch (Array array, object value)
738 throw new ArgumentNullException ("array");
744 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
746 if (array.Length == 0)
749 if (!(value is IComparable))
750 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
752 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
756 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
758 public static int BinarySearch (Array array, object value, IComparer comparer)
761 throw new ArgumentNullException ("array");
764 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
766 if (array.Length == 0)
769 if ((comparer == null) && (value != null) && !(value is IComparable))
770 throw new ArgumentException (Locale.GetText (
771 "comparer is null and value does not support IComparable."));
773 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
777 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
779 public static int BinarySearch (Array array, int index, int length, object value)
782 throw new ArgumentNullException ("array");
785 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
787 if (index < array.GetLowerBound (0))
788 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
789 "index is less than the lower bound of array."));
791 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
792 "Value has to be >= 0."));
793 // re-ordered to avoid possible integer overflow
794 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
795 throw new ArgumentException (Locale.GetText (
796 "index and length do not specify a valid range in array."));
798 if (array.Length == 0)
801 if ((value != null) && (!(value is IComparable)))
802 throw new ArgumentException (Locale.GetText (
803 "value does not support IComparable"));
805 return DoBinarySearch (array, index, length, value, null);
809 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
811 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
814 throw new ArgumentNullException ("array");
817 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
819 if (index < array.GetLowerBound (0))
820 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
821 "index is less than the lower bound of array."));
823 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
824 "Value has to be >= 0."));
825 // re-ordered to avoid possible integer overflow
826 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
827 throw new ArgumentException (Locale.GetText (
828 "index and length do not specify a valid range in array."));
830 if (array.Length == 0)
833 if ((comparer == null) && (value != null) && !(value is IComparable))
834 throw new ArgumentException (Locale.GetText (
835 "comparer is null and value does not support IComparable."));
837 return DoBinarySearch (array, index, length, value, comparer);
840 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
842 // cache this in case we need it
843 if (comparer == null)
844 comparer = Comparer.Default;
847 // Comment from Tum (tum@veridicus.com):
848 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
849 int iMax = index + length - 1;
852 while (iMin <= iMax) {
853 // Be careful with overflow
854 // http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
855 int iMid = iMin + ((iMax - iMin) / 2);
856 object elt = array.GetValueImpl (iMid);
858 iCmp = comparer.Compare (elt, value);
865 iMin = iMid + 1; // compensate for the rounding down
868 catch (Exception e) {
869 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
876 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
878 public static void Clear (Array array, int index, int length)
881 throw new ArgumentNullException ("array");
883 throw new ArgumentOutOfRangeException ("length < 0");
885 int low = array.GetLowerBound (0);
887 throw new IndexOutOfRangeException ("index < lower bound");
890 // re-ordered to avoid possible integer overflow
891 if (index > array.Length - length)
892 throw new IndexOutOfRangeException ("index + length > size");
894 ClearInternal (array, index, length);
897 [MethodImplAttribute (MethodImplOptions.InternalCall)]
898 static extern void ClearInternal (Array a, int index, int count);
900 [MethodImplAttribute (MethodImplOptions.InternalCall)]
905 extern object Clone ();
908 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
910 public static void Copy (Array sourceArray, Array destinationArray, int length)
912 // need these checks here because we are going to use
913 // GetLowerBound() on source and dest.
914 if (sourceArray == null)
915 throw new ArgumentNullException ("sourceArray");
917 if (destinationArray == null)
918 throw new ArgumentNullException ("destinationArray");
920 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
921 destinationArray.GetLowerBound (0), length);
925 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
927 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
929 if (sourceArray == null)
930 throw new ArgumentNullException ("sourceArray");
932 if (destinationArray == null)
933 throw new ArgumentNullException ("destinationArray");
936 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
937 "Value has to be >= 0."));;
940 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
941 "Value has to be >= 0."));;
943 if (destinationIndex < 0)
944 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
945 "Value has to be >= 0."));;
947 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
950 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
951 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
953 // re-ordered to avoid possible integer overflow
954 if (source_pos > sourceArray.Length - length)
955 throw new ArgumentException ("length");
957 if (dest_pos > destinationArray.Length - length) {
958 string msg = "Destination array was not long enough. Check " +
959 "destIndex and length, and the array's lower bounds";
961 throw new ArgumentException (msg, string.Empty);
963 throw new ArgumentException (msg);
967 if (sourceArray.Rank != destinationArray.Rank)
968 throw new RankException (Locale.GetText ("Arrays must be of same size."));
970 Type src_type = sourceArray.GetType ().GetElementType ();
971 Type dst_type = destinationArray.GetType ().GetElementType ();
973 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
974 for (int i = 0; i < length; i++) {
975 Object srcval = sourceArray.GetValueImpl (source_pos + i);
978 destinationArray.SetValueImpl (srcval, dest_pos + i);
980 if (src_type.Equals (typeof (Object)))
981 throw new InvalidCastException ();
983 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
984 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
989 for (int i = length - 1; i >= 0; i--) {
990 Object srcval = sourceArray.GetValueImpl (source_pos + i);
993 destinationArray.SetValueImpl (srcval, dest_pos + i);
995 if (src_type.Equals (typeof (Object)))
996 throw new InvalidCastException ();
998 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
999 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
1007 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1009 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
1010 long destinationIndex, long length)
1012 if (sourceArray == null)
1013 throw new ArgumentNullException ("sourceArray");
1015 if (destinationArray == null)
1016 throw new ArgumentNullException ("destinationArray");
1018 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
1019 throw new ArgumentOutOfRangeException ("sourceIndex",
1020 Locale.GetText ("Must be in the Int32 range."));
1022 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
1023 throw new ArgumentOutOfRangeException ("destinationIndex",
1024 Locale.GetText ("Must be in the Int32 range."));
1026 if (length < 0 || length > Int32.MaxValue)
1027 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1028 "Value must be >= 0 and <= Int32.MaxValue."));
1030 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
1034 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1036 public static void Copy (Array sourceArray, Array destinationArray, long length)
1038 if (length < 0 || length > Int32.MaxValue)
1039 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1040 "Value must be >= 0 and <= Int32.MaxValue."));
1042 Copy (sourceArray, destinationArray, (int) length);
1047 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1049 public static int IndexOf (Array array, object value)
1052 throw new ArgumentNullException ("array");
1054 return IndexOf (array, value, 0, array.Length);
1058 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1060 public static int IndexOf (Array array, object value, int startIndex)
1063 throw new ArgumentNullException ("array");
1065 return IndexOf (array, value, startIndex, array.Length - startIndex);
1069 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1071 public static int IndexOf (Array array, object value, int startIndex, int count)
1074 throw new ArgumentNullException ("array");
1077 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1079 // re-ordered to avoid possible integer overflow
1080 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1081 throw new ArgumentOutOfRangeException ();
1083 int max = startIndex + count;
1084 for (int i = startIndex; i < max; i++) {
1085 if (Object.Equals (array.GetValueImpl (i), value))
1089 return array.GetLowerBound (0) - 1;
1092 public void Initialize()
1094 //FIXME: We would like to find a compiler that uses
1095 // this method. It looks like this method do nothing
1096 // in C# so no exception is trown by the moment.
1100 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1102 public static int LastIndexOf (Array array, object value)
1105 throw new ArgumentNullException ("array");
1107 if (array.Length == 0)
1108 return array.GetLowerBound (0) - 1;
1109 return LastIndexOf (array, value, array.Length - 1);
1113 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1115 public static int LastIndexOf (Array array, object value, int startIndex)
1118 throw new ArgumentNullException ("array");
1120 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
1124 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1126 public static int LastIndexOf (Array array, object value, int startIndex, int count)
1129 throw new ArgumentNullException ("array");
1132 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1134 if (count < 0 || startIndex < array.GetLowerBound (0) ||
1135 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
1136 throw new ArgumentOutOfRangeException ();
1138 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1139 if (Object.Equals (array.GetValueImpl (i), value))
1143 return array.GetLowerBound (0) - 1;
1146 #if !BOOTSTRAP_WITH_OLDLIB
1147 /* delegate used to swap array elements */
1148 delegate void Swapper (int i, int j);
1151 static Swapper get_swapper (Array array)
1154 return new Swapper (array.int_swapper);
1155 if (array is double[])
1156 return new Swapper (array.double_swapper);
1157 if (array is object[]) {
1158 return new Swapper (array.obj_swapper);
1160 return new Swapper (array.slow_swapper);
1164 static Swapper get_swapper<T> (T [] array)
1167 return new Swapper (array.int_swapper);
1168 if (array is double[])
1169 return new Swapper (array.double_swapper);
1171 // gmcs refuses to compile this
1172 //return new Swapper (array.generic_swapper<T>);
1173 return new Swapper (array.slow_swapper);
1178 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1180 public static void Reverse (Array array)
1183 throw new ArgumentNullException ("array");
1185 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
1189 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1191 public static void Reverse (Array array, int index, int length)
1194 throw new ArgumentNullException ("array");
1197 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1199 if (index < array.GetLowerBound (0) || length < 0)
1200 throw new ArgumentOutOfRangeException ();
1202 // re-ordered to avoid possible integer overflow
1203 if (index > array.GetUpperBound (0) + 1 - length)
1204 throw new ArgumentException ();
1206 int end = index + length - 1;
1207 object[] oarray = array as object[];
1208 if (oarray != null) {
1209 while (index < end) {
1210 object tmp = oarray [index];
1211 oarray [index] = oarray [end];
1218 int[] iarray = array as int[];
1219 if (iarray != null) {
1220 while (index < end) {
1221 int tmp = iarray [index];
1222 iarray [index] = iarray [end];
1229 double[] darray = array as double[];
1230 if (darray != null) {
1231 while (index < end) {
1232 double tmp = darray [index];
1233 darray [index] = darray [end];
1241 Swapper swapper = get_swapper (array);
1242 while (index < end) {
1243 swapper (index, end);
1250 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1252 public static void Sort (Array array)
1255 throw new ArgumentNullException ("array");
1257 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
1261 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1263 public static void Sort (Array keys, Array items)
1266 throw new ArgumentNullException ("keys");
1268 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1272 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1274 public static void Sort (Array array, IComparer comparer)
1277 throw new ArgumentNullException ("array");
1279 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1283 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1285 public static void Sort (Array array, int index, int length)
1287 Sort (array, null, index, length, null);
1291 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1293 public static void Sort (Array keys, Array items, IComparer comparer)
1296 throw new ArgumentNullException ("keys");
1298 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1302 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1304 public static void Sort (Array keys, Array items, int index, int length)
1306 Sort (keys, items, index, length, null);
1310 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1312 public static void Sort (Array array, int index, int length, IComparer comparer)
1314 Sort (array, null, index, length, comparer);
1318 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1321 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1324 throw new ArgumentNullException ("keys");
1326 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1327 throw new RankException ();
1329 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1330 throw new ArgumentException ();
1332 if (index < keys.GetLowerBound (0))
1333 throw new ArgumentOutOfRangeException ("index");
1336 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1337 "Value has to be >= 0."));
1339 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1340 throw new ArgumentException ();
1345 if (comparer == null) {
1350 iswapper = get_swapper (items);
1351 if (keys is double[]) {
1352 combsort (keys as double[], index, length, iswapper);
1355 if (keys is int[]) {
1356 combsort (keys as int[], index, length, iswapper);
1359 if (keys is char[]) {
1360 combsort (keys as char[], index, length, iswapper);
1366 int high0 = index + length - 1;
1367 qsort (keys, items, low0, high0, comparer);
1369 catch (Exception e) {
1370 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1374 /* note, these are instance methods */
1375 void int_swapper (int i, int j) {
1376 int[] array = this as int[];
1377 int val = array [i];
1378 array [i] = array [j];
1382 void obj_swapper (int i, int j) {
1383 object[] array = this as object[];
1384 object val = array [i];
1385 array [i] = array [j];
1389 void slow_swapper (int i, int j) {
1390 object val = GetValueImpl (i);
1391 SetValueImpl (GetValue (j), i);
1392 SetValueImpl (val, j);
1395 void double_swapper (int i, int j) {
1396 double[] array = this as double[];
1397 double val = array [i];
1398 array [i] = array [j];
1402 static int new_gap (int gap)
1404 gap = (gap * 10) / 13;
1405 if (gap == 9 || gap == 10)
1412 /* we use combsort because it's fast enough and very small, since we have
1413 * several specialized versions here.
1415 static void combsort (double[] array, int start, int size, Swapper swap_items)
1419 gap = new_gap (gap);
1420 bool swapped = false;
1421 int end = start + size - gap;
1422 for (int i = start; i < end; i++) {
1424 if (array [i] > array [j]) {
1425 double val = array [i];
1426 array [i] = array [j];
1429 if (swap_items != null)
1433 if (gap == 1 && !swapped)
1438 static void combsort (int[] array, int start, int size, Swapper swap_items)
1442 gap = new_gap (gap);
1443 bool swapped = false;
1444 int end = start + size - gap;
1445 for (int i = start; i < end; i++) {
1447 if (array [i] > array [j]) {
1448 int val = array [i];
1449 array [i] = array [j];
1452 if (swap_items != null)
1456 if (gap == 1 && !swapped)
1461 static void combsort (char[] array, int start, int size, Swapper swap_items)
1465 gap = new_gap (gap);
1466 bool swapped = false;
1467 int end = start + size - gap;
1468 for (int i = start; i < end; i++) {
1470 if (array [i] > array [j]) {
1471 char val = array [i];
1472 array [i] = array [j];
1475 if (swap_items != null)
1479 if (gap == 1 && !swapped)
1484 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1492 // Be careful with overflows
1493 int mid = low + ((high - low) / 2);
1494 object objPivot = keys.GetValueImpl (mid);
1497 // Move the walls in
1498 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1500 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1504 swap (keys, items, low, high);
1512 qsort (keys, items, low0, high, comparer);
1514 qsort (keys, items, low, high0, comparer);
1517 private static void swap (Array keys, Array items, int i, int j)
1521 tmp = keys.GetValueImpl (i);
1522 keys.SetValueImpl (keys.GetValue (j), i);
1523 keys.SetValueImpl (tmp, j);
1525 if (items != null) {
1526 tmp = items.GetValueImpl (i);
1527 items.SetValueImpl (items.GetValueImpl (j), i);
1528 items.SetValueImpl (tmp, j);
1532 private static int compare (object value1, object value2, IComparer comparer)
1535 return value2 == null ? 0 : -1;
1536 else if (value2 == null)
1538 else if (comparer == null)
1539 return ((IComparable) value1).CompareTo (value2);
1541 return comparer.Compare (value1, value2);
1545 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1546 public static void Sort<T> (T [] array)
1549 throw new ArgumentNullException ("array");
1551 Sort<T, T> (array, null, 0, array.Length, null);
1554 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1555 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items)
1558 throw new ArgumentNullException ("keys");
1560 Sort<TKey, TValue> (keys, items, 0, keys.Length, null);
1563 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1564 public static void Sort<T> (T [] array, IComparer<T> comparer)
1567 throw new ArgumentNullException ("array");
1569 Sort<T, T> (array, null, 0, array.Length, comparer);
1572 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1573 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, IComparer<TKey> comparer)
1576 throw new ArgumentNullException ("keys");
1578 Sort<TKey, TValue> (keys, items, 0, keys.Length, comparer);
1581 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1582 public static void Sort<T> (T [] array, int index, int length)
1585 throw new ArgumentNullException ("array");
1587 Sort<T, T> (array, null, index, length, null);
1590 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1591 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length)
1593 Sort<TKey, TValue> (keys, items, index, length, null);
1596 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1597 public static void Sort<T> (T [] array, int index, int length, IComparer<T> comparer)
1600 throw new ArgumentNullException ("array");
1602 Sort<T, T> (array, null, index, length, comparer);
1605 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1606 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length, IComparer<TKey> comparer)
1609 throw new ArgumentNullException ("keys");
1612 throw new ArgumentOutOfRangeException ("index");
1615 throw new ArgumentOutOfRangeException ("length");
1617 if (keys.Length - index < length
1618 || (items != null && index > items.Length - length))
1619 throw new ArgumentException ();
1625 // Check for value types which can be sorted without Compare () method
1627 if (comparer == null) {
1632 iswapper = get_swapper<TValue> (items);
1633 if (keys is double[]) {
1634 combsort (keys as double[], index, length, iswapper);
1637 if (keys is int[]) {
1638 combsort (keys as int[], index, length, iswapper);
1641 if (keys is char[]) {
1642 combsort (keys as char[], index, length, iswapper);
1646 // Use Comparer<T>.Default instead
1647 // comparer = Comparer<K>.Default;
1652 int high0 = index + length - 1;
1653 qsort<TKey, TValue> (keys, items, low0, high0, comparer);
1655 catch (Exception e) {
1656 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1660 public static void Sort<T> (T [] array, Comparison<T> comparison)
1663 throw new ArgumentNullException ("array");
1664 Sort<T> (array, array.Length, comparison);
1667 internal static void Sort<T> (T [] array, int length, Comparison<T> comparison)
1669 if (comparison == null)
1670 throw new ArgumentNullException ("comparison");
1672 if (length <= 1 || array.Length <= 1)
1677 int high0 = length - 1;
1678 qsort<T> (array, low0, high0, comparison);
1680 catch (Exception e) {
1681 throw new InvalidOperationException (Locale.GetText ("Comparison threw an exception."), e);
1685 private static void qsort<K, V> (K [] keys, V [] items, int low0, int high0, IComparer<K> comparer)
1693 // Be careful with overflows
1694 int mid = low + ((high - low) / 2);
1695 K keyPivot = keys [mid];
1698 // Move the walls in
1699 //while (low < high0 && comparer.Compare (keys [low], keyPivot) < 0)
1700 while (low < high0 && compare (keys [low], keyPivot, comparer) < 0)
1702 //while (high > low0 && comparer.Compare (keyPivot, keys [high]) < 0)
1703 while (high > low0 && compare (keyPivot, keys [high], comparer) < 0)
1707 swap<K, V> (keys, items, low, high);
1715 qsort<K, V> (keys, items, low0, high, comparer);
1717 qsort<K, V> (keys, items, low, high0, comparer);
1720 private static int compare<T> (T value1, T value2, IComparer<T> comparer)
1722 if (comparer != null)
1723 return comparer.Compare (value1, value2);
1724 else if (value1 == null)
1725 return value2 == null ? 0 : -1;
1726 else if (value2 == null)
1728 else if (value1 is IComparable<T>)
1729 return ((IComparable<T>) value1).CompareTo (value2);
1730 else if (value1 is IComparable)
1731 return ((IComparable) value1).CompareTo (value2);
1733 string msg = Locale.GetText ("No IComparable or IComparable<{0}> interface found.");
1734 throw new InvalidOperationException (String.Format (msg, typeof (T)));
1737 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1745 // Be careful with overflows
1746 int mid = low + ((high - low) / 2);
1747 T keyPivot = array [mid];
1750 // Move the walls in
1751 while (low < high0 && comparison (array [low], keyPivot) < 0)
1753 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1757 swap<T> (array, low, high);
1765 qsort<T> (array, low0, high, comparison);
1767 qsort<T> (array, low, high0, comparison);
1770 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1775 keys [i] = keys [j];
1778 if (items != null) {
1781 items [i] = items [j];
1786 private static void swap<T> (T [] array, int i, int j)
1789 array [i] = array [j];
1798 void CopyTo (Array array, int index)
1801 throw new ArgumentNullException ("array");
1803 // The order of these exception checks may look strange,
1804 // but that's how the microsoft runtime does it.
1806 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1807 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1808 throw new ArgumentException ("Destination array was not long " +
1809 "enough. Check destIndex and length, and the array's " +
1812 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1814 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1815 "Value has to be >= 0."));
1817 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1821 [ComVisible (false)]
1826 void CopyTo (Array array, long index)
1828 if (index < 0 || index > Int32.MaxValue)
1829 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1830 "Value must be >= 0 and <= Int32.MaxValue."));
1832 CopyTo (array, (int) index);
1836 internal class SimpleEnumerator : IEnumerator, ICloneable
1842 public SimpleEnumerator (Array arrayToEnumerate)
1844 this.enumeratee = arrayToEnumerate;
1845 this.currentpos = -1;
1846 this.length = arrayToEnumerate.Length;
1849 public object Current {
1851 // Exception messages based on MS implementation
1852 if (currentpos < 0 )
1853 throw new InvalidOperationException (Locale.GetText (
1854 "Enumeration has not started."));
1855 if (currentpos >= length)
1856 throw new InvalidOperationException (Locale.GetText (
1857 "Enumeration has already ended"));
1858 // Current should not increase the position. So no ++ over here.
1859 return enumeratee.GetValueImpl (currentpos);
1863 public bool MoveNext()
1865 //The docs say Current should throw an exception if last
1866 //call to MoveNext returned false. This means currentpos
1867 //should be set to length when returning false.
1868 if (currentpos < length)
1870 if(currentpos < length)
1881 public object Clone ()
1883 return MemberwiseClone ();
1888 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1889 public static void Resize<T> (ref T [] array, int newSize)
1891 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1894 internal static void Resize<T> (ref T[] array, int length, int newSize)
1897 throw new ArgumentOutOfRangeException ();
1899 if (array == null) {
1900 array = new T [newSize];
1904 if (array.Length == newSize)
1907 T [] a = new T [newSize];
1908 Array.Copy (array, a, Math.Min (newSize, length));
1912 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1915 throw new ArgumentNullException ("array");
1917 throw new ArgumentNullException ("match");
1919 foreach (T t in array)
1926 public static void ForEach<T> (T [] array, Action <T> action)
1929 throw new ArgumentNullException ("array");
1931 throw new ArgumentNullException ("action");
1933 foreach (T t in array)
1937 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1940 throw new ArgumentNullException ("array");
1941 if (converter == null)
1942 throw new ArgumentNullException ("converter");
1944 TOutput [] output = new TOutput [array.Length];
1945 for (int i = 0; i < array.Length; i ++)
1946 output [i] = converter (array [i]);
1951 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1954 throw new ArgumentNullException ("array");
1956 return FindLastIndex<T> (array, 0, array.Length, match);
1959 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1962 throw new ArgumentNullException ();
1964 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1967 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1970 throw new ArgumentNullException ("array");
1972 throw new ArgumentNullException ("match");
1974 if (startIndex > array.Length || startIndex + count > array.Length)
1975 throw new ArgumentOutOfRangeException ();
1977 for (int i = startIndex + count - 1; i >= startIndex; i--)
1978 if (match (array [i]))
1984 public static int FindIndex<T> (T [] array, Predicate<T> match)
1987 throw new ArgumentNullException ("array");
1989 return FindIndex<T> (array, 0, array.Length, match);
1992 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1995 throw new ArgumentNullException ("array");
1997 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
2000 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
2003 throw new ArgumentNullException ("array");
2006 throw new ArgumentNullException ("match");
2008 if (startIndex > array.Length || startIndex + count > array.Length)
2009 throw new ArgumentOutOfRangeException ();
2011 for (int i = startIndex; i < startIndex + count; i ++)
2012 if (match (array [i]))
2018 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
2019 public static int BinarySearch<T> (T [] array, T value)
2022 throw new ArgumentNullException ("array");
2024 return BinarySearch<T> (array, 0, array.Length, value, null);
2027 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
2028 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
2031 throw new ArgumentNullException ("array");
2033 return BinarySearch<T> (array, 0, array.Length, value, comparer);
2036 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
2037 public static int BinarySearch<T> (T [] array, int index, int length, T value)
2039 return BinarySearch<T> (array, index, length, value, null);
2042 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
2043 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
2046 throw new ArgumentNullException ("array");
2048 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
2049 "index is less than the lower bound of array."));
2051 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
2052 "Value has to be >= 0."));
2053 // re-ordered to avoid possible integer overflow
2054 if (index > array.Length - length)
2055 throw new ArgumentException (Locale.GetText (
2056 "index and length do not specify a valid range in array."));
2057 if (comparer == null)
2058 comparer = Comparer <T>.Default;
2061 int iMax = index + length - 1;
2064 while (iMin <= iMax) {
2065 // Be careful with overflows
2066 int iMid = iMin + ((iMax - iMin) / 2);
2067 iCmp = comparer.Compare (value, array [iMid]);
2074 iMin = iMid + 1; // compensate for the rounding down
2076 } catch (Exception e) {
2077 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
2083 public static int IndexOf<T> (T [] array, T value)
2086 throw new ArgumentNullException ("array");
2088 return IndexOf<T> (array, value, 0, array.Length);
2091 public static int IndexOf<T> (T [] array, T value, int startIndex)
2094 throw new ArgumentNullException ("array");
2096 return IndexOf<T> (array, value, startIndex, array.Length - startIndex);
2099 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
2102 throw new ArgumentNullException ("array");
2104 // re-ordered to avoid possible integer overflow
2105 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
2106 throw new ArgumentOutOfRangeException ();
2108 int max = startIndex + count;
2109 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2110 for (int i = startIndex; i < max; i++) {
2111 if (equalityComparer.Equals (array [i], value))
2118 public static int LastIndexOf<T> (T [] array, T value)
2121 throw new ArgumentNullException ("array");
2123 if (array.Length == 0)
2125 return LastIndexOf<T> (array, value, array.Length - 1);
2128 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
2131 throw new ArgumentNullException ("array");
2133 return LastIndexOf<T> (array, value, startIndex, startIndex + 1);
2136 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
2139 throw new ArgumentNullException ("array");
2141 if (count < 0 || startIndex < array.GetLowerBound (0) ||
2142 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
2143 throw new ArgumentOutOfRangeException ();
2145 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2146 for (int i = startIndex; i >= startIndex - count + 1; i--) {
2147 if (equalityComparer.Equals (array [i], value))
2154 public static T [] FindAll<T> (T [] array, Predicate <T> match)
2157 throw new ArgumentNullException ("array");
2160 throw new ArgumentNullException ("match");
2163 T [] d = new T [array.Length];
2164 foreach (T t in array)
2168 Resize <T> (ref d, pos);
2172 public static bool Exists<T> (T [] array, Predicate <T> match)
2175 throw new ArgumentNullException ("array");
2178 throw new ArgumentNullException ("match");
2180 foreach (T t in array)
2186 public static ReadOnlyCollection<T> AsReadOnly<T> (T[] array)
2189 throw new ArgumentNullException ("array");
2190 return new ReadOnlyCollection<T> (new ArrayReadOnlyList<T> (array));
2193 public static T Find<T> (T [] array, Predicate<T> match)
2196 throw new ArgumentNullException ("array");
2199 throw new ArgumentNullException ("match");
2201 foreach (T t in array)
2208 public static T FindLast<T> (T [] array, Predicate <T> match)
2211 throw new ArgumentNullException ("array");
2214 throw new ArgumentNullException ("match");
2216 for (int i = array.Length - 1; i >= 0; i--)
2217 if (match (array [i]))
2223 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
2225 // The constrained copy should guarantee that if there is an exception thrown
2226 // during the copy, the destination array remains unchanged.
2227 // This is related to System.Runtime.Reliability.CER
2228 public static void ConstrainedCopy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
2230 Copy (sourceArray, sourceIndex, destinationArray, destinationIndex, length);
2235 class ArrayReadOnlyList<T> : IList<T>
2239 public ArrayReadOnlyList (T [] array)
2244 public T this [int index] {
2246 if (unchecked ((uint) index) >= unchecked ((uint) array.Length))
2247 throw new ArgumentOutOfRangeException ("index");
2248 return array [index];
2250 set { throw ReadOnlyError (); }
2254 get { return array.Length; }
2257 public bool IsReadOnly {
2258 get { return true; }
2261 public void Add (T item)
2263 throw ReadOnlyError ();
2266 public void Clear ()
2268 throw ReadOnlyError ();
2271 public bool Contains (T item)
2273 return Array.IndexOf<T> (array, item) >= 0;
2276 public void CopyTo (T [] array, int index)
2278 array.CopyTo (array, index);
2281 IEnumerator IEnumerable.GetEnumerator ()
2283 return GetEnumerator ();
2286 public IEnumerator<T> GetEnumerator ()
2288 for (int i = 0; i < array.Length; i++)
2289 yield return array [i];
2292 public int IndexOf (T item)
2294 return Array.IndexOf<T> (array, item);
2297 public void Insert (int index, T item)
2299 throw ReadOnlyError ();
2302 public bool Remove (T item)
2304 throw ReadOnlyError ();
2307 public void RemoveAt (int index)
2309 throw ReadOnlyError ();
2312 static Exception ReadOnlyError ()
2314 return new NotSupportedException ("This collection is read-only.");
2320 #if BOOTSTRAP_WITH_OLDLIB
2321 /* delegate used to swap array elements, keep defined outside Array */
2322 delegate void Swapper (int i, int j);