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;
46 // FIXME: We are doing way to many double/triple exception checks for the overloaded functions"
47 // FIXME: Sort overloads parameter checks are VERY inconsistent"
48 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
56 protected int InternalArray__ICollection_get_Count<T> ()
61 protected IEnumerator<T> InternalArray__IEnumerable_GetEnumerator<T> ()
63 return new InternalEnumerator<T> (this);
66 protected void InternalArray__ICollection_Clear<T> ()
68 throw new NotSupportedException ("Collection is read-only");
71 protected void InternalArray__ICollection_Add<T> (T item)
73 throw new NotSupportedException ("Collection is read-only");
76 protected bool InternalArray__ICollection_Remove<T> (T item)
78 throw new NotSupportedException ("Collection is read-only");
81 protected bool InternalArray__ICollection_Contains<T> (T item)
84 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
86 int length = this.Length;
87 for (int i = 0; i < length; i++) {
89 GetGenericValueImpl (i, out value);
97 if (item.Equals (value))
104 protected void InternalArray__ICollection_CopyTo<T> (T[] array, int index)
107 throw new ArgumentNullException ("array");
109 // The order of these exception checks may look strange,
110 // but that's how the microsoft runtime does it.
112 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
113 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
114 throw new ArgumentException ();
116 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
118 throw new ArgumentOutOfRangeException (
119 "index", Locale.GetText ("Value has to be >= 0."));
121 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
124 protected void InternalArray__Insert<T> (int index, T item)
126 throw new NotSupportedException ("Collection is read-only");
129 protected void InternalArray__RemoveAt<T> (int index)
131 throw new NotSupportedException ("Collection is read-only");
134 protected int InternalArray__IndexOf<T> (T item)
137 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
139 int length = this.Length;
140 for (int i = 0; i < length; i++) {
142 GetGenericValueImpl (i, out value);
145 return i + this.GetLowerBound (0);
148 return this.GetLowerBound (0) - 1;
152 if (item.Equals (value))
153 // array index may not be zero-based.
155 return i + this.GetLowerBound (0);
160 // lower bound may be MinValue
161 retVal = this.GetLowerBound (0) - 1;
167 protected T InternalArray__get_Item<T> (int index)
169 if (unchecked ((uint) index) >= unchecked ((uint) Length))
170 throw new ArgumentOutOfRangeException ("index");
173 GetGenericValueImpl (index, out value);
177 protected void InternalArray__set_Item<T> (int index, T item)
179 throw new NotSupportedException ("Collection is read-only");
182 // CAUTION! No bounds checking!
183 [MethodImplAttribute (MethodImplOptions.InternalCall)]
184 internal extern void GetGenericValueImpl<T> (int pos, out T value);
186 internal struct InternalEnumerator<T> : IEnumerator<T>
188 const int NOT_STARTED = -2;
190 // this MUST be -1, because we depend on it in move next.
191 // we just decr the size, so, 0 - 1 == FINISHED
192 const int FINISHED = -1;
197 internal InternalEnumerator (Array array)
203 public void Dispose ()
208 public bool MoveNext ()
210 if (idx == NOT_STARTED)
213 return idx != FINISHED && -- idx != FINISHED;
219 throw new InvalidOperationException ();
221 return array.InternalArray__get_Item<T> (array.Length - 1 - idx);
225 void IEnumerator.Reset ()
227 throw new NotImplementedException ();
230 object IEnumerator.Current {
241 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
244 int length = this.GetLength (0);
246 for (int i = 1; i < this.Rank; i++) {
247 length *= this.GetLength (i);
255 public long LongLength {
257 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
259 get { return Length; }
265 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
268 return this.GetRank ();
273 object IList.this [int index] {
275 if (unchecked ((uint) index) >= unchecked ((uint) Length))
276 throw new ArgumentOutOfRangeException ("index");
277 return GetValueImpl (index);
280 if (unchecked ((uint) index) >= unchecked ((uint) Length))
281 throw new ArgumentOutOfRangeException ("index");
282 SetValueImpl (value, index);
286 int IList.Add (object value)
288 throw new NotSupportedException ();
293 Array.Clear (this, this.GetLowerBound (0), this.Length);
296 bool IList.Contains (object value)
299 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
301 int length = this.Length;
302 for (int i = 0; i < length; i++) {
303 if (Object.Equals (value, this.GetValueImpl (i)))
310 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
312 int IList.IndexOf (object value)
315 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
317 int length = this.Length;
318 for (int i = 0; i < length; i++) {
319 if (Object.Equals (value, this.GetValueImpl (i)))
320 // array index may not be zero-based.
322 return i + this.GetLowerBound (0);
327 // lower bound may be MinValue
328 retVal = this.GetLowerBound (0) - 1;
334 void IList.Insert (int index, object value)
336 throw new NotSupportedException ();
339 void IList.Remove (object value)
341 throw new NotSupportedException ();
344 void IList.RemoveAt (int index)
346 throw new NotSupportedException ();
349 // InternalCall Methods
350 [MethodImplAttribute (MethodImplOptions.InternalCall)]
351 extern int GetRank ();
353 [MethodImplAttribute (MethodImplOptions.InternalCall)]
354 public extern int GetLength (int dimension);
358 public long GetLongLength (int dimension)
360 return GetLength (dimension);
365 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
367 [MethodImplAttribute (MethodImplOptions.InternalCall)]
368 public extern int GetLowerBound (int dimension);
370 [MethodImplAttribute (MethodImplOptions.InternalCall)]
371 public extern object GetValue (params int[] indices);
373 [MethodImplAttribute (MethodImplOptions.InternalCall)]
374 public extern void SetValue (object value, params int[] indices);
376 // CAUTION! No bounds checking!
377 [MethodImplAttribute (MethodImplOptions.InternalCall)]
378 internal extern object GetValueImpl (int pos);
380 // CAUTION! No bounds checking!
381 [MethodImplAttribute (MethodImplOptions.InternalCall)]
382 internal extern void SetValueImpl (object value, int pos);
384 [MethodImplAttribute (MethodImplOptions.InternalCall)]
385 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
387 [MethodImplAttribute (MethodImplOptions.InternalCall)]
388 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
391 int ICollection.Count {
401 bool IsSynchronized {
441 IEnumerator GetEnumerator ()
443 return new SimpleEnumerator (this);
447 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
449 public int GetUpperBound (int dimension)
451 return GetLowerBound (dimension) + GetLength (dimension) - 1;
454 public object GetValue (int index)
457 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
458 if (index < GetLowerBound (0) || index > GetUpperBound (0))
459 throw new IndexOutOfRangeException (Locale.GetText (
460 "Index has to be between upper and lower bound of the array."));
462 return GetValueImpl (index - GetLowerBound (0));
465 public object GetValue (int index1, int index2)
467 int[] ind = {index1, index2};
468 return GetValue (ind);
471 public object GetValue (int index1, int index2, int index3)
473 int[] ind = {index1, index2, index3};
474 return GetValue (ind);
479 public object GetValue (long index)
481 if (index < 0 || index > Int32.MaxValue)
482 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
483 "Value must be >= 0 and <= Int32.MaxValue."));
485 return GetValue ((int) index);
489 public object GetValue (long index1, long index2)
491 if (index1 < 0 || index1 > Int32.MaxValue)
492 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
493 "Value must be >= 0 and <= Int32.MaxValue."));
495 if (index2 < 0 || index2 > Int32.MaxValue)
496 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
497 "Value must be >= 0 and <= Int32.MaxValue."));
499 return GetValue ((int) index1, (int) index2);
503 public object GetValue (long index1, long index2, long index3)
505 if (index1 < 0 || index1 > Int32.MaxValue)
506 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
507 "Value must be >= 0 and <= Int32.MaxValue."));
509 if (index2 < 0 || index2 > Int32.MaxValue)
510 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
511 "Value must be >= 0 and <= Int32.MaxValue."));
513 if (index3 < 0 || index3 > Int32.MaxValue)
514 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
515 "Value must be >= 0 and <= Int32.MaxValue."));
517 return GetValue ((int) index1, (int) index2, (int) index3);
521 public void SetValue (object value, long index)
523 if (index < 0 || index > Int32.MaxValue)
524 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
525 "Value must be >= 0 and <= Int32.MaxValue."));
527 SetValue (value, (int) index);
531 public void SetValue (object value, long index1, long index2)
533 if (index1 < 0 || index1 > Int32.MaxValue)
534 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
535 "Value must be >= 0 and <= Int32.MaxValue."));
537 if (index2 < 0 || index2 > Int32.MaxValue)
538 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
539 "Value must be >= 0 and <= Int32.MaxValue."));
541 int[] ind = {(int) index1, (int) index2};
542 SetValue (value, ind);
546 public void SetValue (object value, long index1, long index2, long index3)
548 if (index1 < 0 || index1 > Int32.MaxValue)
549 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
550 "Value must be >= 0 and <= Int32.MaxValue."));
552 if (index2 < 0 || index2 > Int32.MaxValue)
553 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
554 "Value must be >= 0 and <= Int32.MaxValue."));
556 if (index3 < 0 || index3 > Int32.MaxValue)
557 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
558 "Value must be >= 0 and <= Int32.MaxValue."));
560 int[] ind = {(int) index1, (int) index2, (int) index3};
561 SetValue (value, ind);
565 public void SetValue (object value, int index)
568 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
569 if (index < GetLowerBound (0) || index > GetUpperBound (0))
570 throw new IndexOutOfRangeException (Locale.GetText (
571 "Index has to be >= lower bound and <= upper bound of the array."));
573 SetValueImpl (value, index - GetLowerBound (0));
576 public void SetValue (object value, int index1, int index2)
578 int[] ind = {index1, index2};
579 SetValue (value, ind);
582 public void SetValue (object value, int index1, int index2, int index3)
584 int[] ind = {index1, index2, index3};
585 SetValue (value, ind);
588 public static Array CreateInstance (Type elementType, int length)
590 int[] lengths = {length};
592 return CreateInstance (elementType, lengths);
595 public static Array CreateInstance (Type elementType, int length1, int length2)
597 int[] lengths = {length1, length2};
599 return CreateInstance (elementType, lengths);
602 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
604 int[] lengths = {length1, length2, length3};
606 return CreateInstance (elementType, lengths);
609 public static Array CreateInstance (Type elementType, params int[] lengths)
611 if (elementType == null)
612 throw new ArgumentNullException ("elementType");
614 throw new ArgumentNullException ("lengths");
616 if (lengths.Length > 255)
617 throw new TypeLoadException ();
621 elementType = elementType.UnderlyingSystemType;
622 if (!elementType.IsSystemType)
623 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
625 return CreateInstanceImpl (elementType, lengths, bounds);
628 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
630 if (elementType == null)
631 throw new ArgumentNullException ("elementType");
633 throw new ArgumentNullException ("lengths");
635 throw new ArgumentNullException ("bounds");
637 elementType = elementType.UnderlyingSystemType;
638 if (!elementType.IsSystemType)
639 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
641 if (lengths.Length < 1)
642 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
644 if (lengths.Length != bounds.Length)
645 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
647 for (int j = 0; j < bounds.Length; j ++) {
649 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
650 "Each value has to be >= 0."));
651 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
652 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
653 "Length + bound must not exceed Int32.MaxValue."));
656 if (lengths.Length > 255)
657 throw new TypeLoadException ();
659 return CreateInstanceImpl (elementType, lengths, bounds);
663 static int [] GetIntArray (long [] values)
665 int len = values.Length;
666 int [] ints = new int [len];
667 for (int i = 0; i < len; i++) {
668 long current = values [i];
669 if (current < 0 || current > (long) Int32.MaxValue)
670 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
671 "Each value has to be >= 0 and <= Int32.MaxValue."));
673 ints [i] = (int) current;
678 public static Array CreateInstance (Type elementType, params long [] lengths)
682 throw new ArgumentNullException ("lengths");
684 return CreateInstance (elementType, GetIntArray (lengths));
688 public object GetValue (params long [] indices)
692 throw new ArgumentNullException ("indices");
694 return GetValue (GetIntArray (indices));
698 public void SetValue (object value, params long [] indices)
702 throw new ArgumentNullException ("indices");
704 SetValue (value, GetIntArray (indices));
709 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
711 public static int BinarySearch (Array array, object value)
714 throw new ArgumentNullException ("array");
720 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
722 if (array.Length == 0)
725 if (!(value is IComparable))
726 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
728 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
732 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
734 public static int BinarySearch (Array array, object value, IComparer comparer)
737 throw new ArgumentNullException ("array");
740 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
742 if (array.Length == 0)
745 if ((comparer == null) && (value != null) && !(value is IComparable))
746 throw new ArgumentException (Locale.GetText (
747 "comparer is null and value does not support IComparable."));
749 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
753 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
755 public static int BinarySearch (Array array, int index, int length, object value)
758 throw new ArgumentNullException ("array");
761 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
763 if (index < array.GetLowerBound (0))
764 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
765 "index is less than the lower bound of array."));
767 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
768 "Value has to be >= 0."));
769 // re-ordered to avoid possible integer overflow
770 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
771 throw new ArgumentException (Locale.GetText (
772 "index and length do not specify a valid range in array."));
774 if (array.Length == 0)
777 if ((value != null) && (!(value is IComparable)))
778 throw new ArgumentException (Locale.GetText (
779 "value does not support IComparable"));
781 return DoBinarySearch (array, index, length, value, null);
785 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
787 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
790 throw new ArgumentNullException ("array");
793 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
795 if (index < array.GetLowerBound (0))
796 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
797 "index is less than the lower bound of array."));
799 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
800 "Value has to be >= 0."));
801 // re-ordered to avoid possible integer overflow
802 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
803 throw new ArgumentException (Locale.GetText (
804 "index and length do not specify a valid range in array."));
806 if (array.Length == 0)
809 if ((comparer == null) && (value != null) && !(value is IComparable))
810 throw new ArgumentException (Locale.GetText (
811 "comparer is null and value does not support IComparable."));
813 return DoBinarySearch (array, index, length, value, comparer);
816 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
818 // cache this in case we need it
819 if (comparer == null)
820 comparer = Comparer.Default;
823 // Comment from Tum (tum@veridicus.com):
824 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
825 int iMax = index + length - 1;
828 while (iMin <= iMax) {
829 int iMid = (iMin + iMax) / 2;
830 object elt = array.GetValueImpl (iMid);
832 iCmp = comparer.Compare (elt, value);
839 iMin = iMid + 1; // compensate for the rounding down
842 catch (Exception e) {
843 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
850 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
852 public static void Clear (Array array, int index, int length)
855 throw new ArgumentNullException ("array");
857 throw new ArgumentOutOfRangeException ("length < 0");
859 int low = array.GetLowerBound (0);
861 throw new IndexOutOfRangeException ("index < lower bound");
864 // re-ordered to avoid possible integer overflow
865 if (index > array.Length - length)
866 throw new IndexOutOfRangeException ("index + length > size");
868 ClearInternal (array, index, length);
871 [MethodImplAttribute (MethodImplOptions.InternalCall)]
872 static extern void ClearInternal (Array a, int index, int count);
874 [MethodImplAttribute (MethodImplOptions.InternalCall)]
879 extern object Clone ();
882 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
884 public static void Copy (Array sourceArray, Array destinationArray, int length)
886 // need these checks here because we are going to use
887 // GetLowerBound() on source and dest.
888 if (sourceArray == null)
889 throw new ArgumentNullException ("sourceArray");
891 if (destinationArray == null)
892 throw new ArgumentNullException ("destinationArray");
894 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
895 destinationArray.GetLowerBound (0), length);
899 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
901 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
903 if (sourceArray == null)
904 throw new ArgumentNullException ("sourceArray");
906 if (destinationArray == null)
907 throw new ArgumentNullException ("destinationArray");
910 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
911 "Value has to be >= 0."));;
914 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
915 "Value has to be >= 0."));;
917 if (destinationIndex < 0)
918 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
919 "Value has to be >= 0."));;
921 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
924 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
925 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
927 // re-ordered to avoid possible integer overflow
928 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
929 throw new ArgumentException ("length");
931 if (sourceArray.Rank != destinationArray.Rank)
932 throw new RankException (Locale.GetText ("Arrays must be of same size."));
934 Type src_type = sourceArray.GetType ().GetElementType ();
935 Type dst_type = destinationArray.GetType ().GetElementType ();
937 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
938 for (int i = 0; i < length; i++) {
939 Object srcval = sourceArray.GetValueImpl (source_pos + i);
942 destinationArray.SetValueImpl (srcval, dest_pos + i);
944 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
945 (src_type.Equals (typeof (Object))))
946 throw new InvalidCastException ();
948 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
949 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
954 for (int i = length - 1; i >= 0; i--) {
955 Object srcval = sourceArray.GetValueImpl (source_pos + i);
958 destinationArray.SetValueImpl (srcval, dest_pos + i);
960 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
961 (src_type.Equals (typeof (Object))))
962 throw new InvalidCastException ();
964 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
965 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
973 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
975 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
976 long destinationIndex, long length)
978 if (sourceArray == null)
979 throw new ArgumentNullException ("sourceArray");
981 if (destinationArray == null)
982 throw new ArgumentNullException ("destinationArray");
984 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
985 throw new ArgumentOutOfRangeException ("sourceIndex",
986 Locale.GetText ("Must be in the Int32 range."));
988 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
989 throw new ArgumentOutOfRangeException ("destinationIndex",
990 Locale.GetText ("Must be in the Int32 range."));
992 if (length < 0 || length > Int32.MaxValue)
993 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
994 "Value must be >= 0 and <= Int32.MaxValue."));
996 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
1000 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1002 public static void Copy (Array sourceArray, Array destinationArray, long length)
1004 if (length < 0 || length > Int32.MaxValue)
1005 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1006 "Value must be >= 0 and <= Int32.MaxValue."));
1008 Copy (sourceArray, destinationArray, (int) length);
1013 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1015 public static int IndexOf (Array array, object value)
1018 throw new ArgumentNullException ("array");
1020 return IndexOf (array, value, 0, array.Length);
1024 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1026 public static int IndexOf (Array array, object value, int startIndex)
1029 throw new ArgumentNullException ("array");
1031 return IndexOf (array, value, startIndex, array.Length - startIndex);
1035 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1037 public static int IndexOf (Array array, object value, int startIndex, int count)
1040 throw new ArgumentNullException ("array");
1043 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1045 // re-ordered to avoid possible integer overflow
1046 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1047 throw new ArgumentOutOfRangeException ();
1049 int max = startIndex + count;
1050 for (int i = startIndex; i < max; i++) {
1051 if (Object.Equals (value, array.GetValueImpl (i)))
1055 return array.GetLowerBound (0) - 1;
1058 public void Initialize()
1060 //FIXME: We would like to find a compiler that uses
1061 // this method. It looks like this method do nothing
1062 // in C# so no exception is trown by the moment.
1066 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1068 public static int LastIndexOf (Array array, object value)
1071 throw new ArgumentNullException ("array");
1073 return LastIndexOf (array, value, array.Length - 1);
1077 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1079 public static int LastIndexOf (Array array, object value, int startIndex)
1082 throw new ArgumentNullException ("array");
1084 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
1088 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1090 public static int LastIndexOf (Array array, object value, int startIndex, int count)
1093 throw new ArgumentNullException ("array");
1096 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1098 if (count < 0 || startIndex < array.GetLowerBound (0) ||
1099 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
1100 throw new ArgumentOutOfRangeException ();
1102 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1103 if (Object.Equals (value, array.GetValueImpl (i)))
1107 return array.GetLowerBound (0) - 1;
1110 #if !BOOTSTRAP_WITH_OLDLIB
1111 /* delegate used to swap array elements */
1112 delegate void Swapper (int i, int j);
1115 static Swapper get_swapper (Array array)
1118 return new Swapper (array.int_swapper);
1119 if (array is double[])
1120 return new Swapper (array.double_swapper);
1121 if (array is object[]) {
1122 return new Swapper (array.obj_swapper);
1124 return new Swapper (array.slow_swapper);
1128 static Swapper get_swapper<T> (T [] array)
1131 return new Swapper (array.int_swapper);
1132 if (array is double[])
1133 return new Swapper (array.double_swapper);
1135 return new Swapper (array.obj_swapper);
1140 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1142 public static void Reverse (Array array)
1145 throw new ArgumentNullException ("array");
1147 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
1151 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1153 public static void Reverse (Array array, int index, int length)
1156 throw new ArgumentNullException ("array");
1159 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1161 if (index < array.GetLowerBound (0) || length < 0)
1162 throw new ArgumentOutOfRangeException ();
1164 // re-ordered to avoid possible integer overflow
1165 if (index > array.GetUpperBound (0) + 1 - length)
1166 throw new ArgumentException ();
1168 int end = index + length - 1;
1169 object[] oarray = array as object[];
1170 if (oarray != null) {
1171 while (index < end) {
1172 object tmp = oarray [index];
1173 oarray [index] = oarray [end];
1180 int[] iarray = array as int[];
1181 if (iarray != null) {
1182 while (index < end) {
1183 int tmp = iarray [index];
1184 iarray [index] = iarray [end];
1191 double[] darray = array as double[];
1192 if (darray != null) {
1193 while (index < end) {
1194 double tmp = darray [index];
1195 darray [index] = darray [end];
1203 Swapper swapper = get_swapper (array);
1204 while (index < end) {
1205 swapper (index, end);
1212 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1214 public static void Sort (Array array)
1217 throw new ArgumentNullException ("array");
1219 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
1223 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1225 public static void Sort (Array keys, Array items)
1228 throw new ArgumentNullException ("keys");
1230 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1234 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1236 public static void Sort (Array array, IComparer comparer)
1239 throw new ArgumentNullException ("array");
1241 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1245 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1247 public static void Sort (Array array, int index, int length)
1249 Sort (array, null, index, length, null);
1253 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1255 public static void Sort (Array keys, Array items, IComparer comparer)
1258 throw new ArgumentNullException ("keys");
1260 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1264 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1266 public static void Sort (Array keys, Array items, int index, int length)
1268 Sort (keys, items, index, length, null);
1272 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1274 public static void Sort (Array array, int index, int length, IComparer comparer)
1276 Sort (array, null, index, length, comparer);
1280 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1283 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1286 throw new ArgumentNullException ("keys");
1288 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1289 throw new RankException ();
1291 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1292 throw new ArgumentException ();
1294 if (index < keys.GetLowerBound (0))
1295 throw new ArgumentOutOfRangeException ("index");
1298 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1299 "Value has to be >= 0."));
1301 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1302 throw new ArgumentException ();
1307 if (comparer == null) {
1312 iswapper = get_swapper (items);
1313 if (keys is double[]) {
1314 combsort (keys as double[], index, length, iswapper);
1317 if (keys is int[]) {
1318 combsort (keys as int[], index, length, iswapper);
1321 if (keys is char[]) {
1322 combsort (keys as char[], index, length, iswapper);
1328 int high0 = index + length - 1;
1329 qsort (keys, items, low0, high0, comparer);
1331 catch (Exception e) {
1332 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1336 /* note, these are instance methods */
1337 void int_swapper (int i, int j) {
1338 int[] array = this as int[];
1339 int val = array [i];
1340 array [i] = array [j];
1344 void obj_swapper (int i, int j) {
1345 object[] array = this as object[];
1346 object val = array [i];
1347 array [i] = array [j];
1351 void slow_swapper (int i, int j) {
1352 object val = GetValueImpl (i);
1353 SetValueImpl (GetValue (j), i);
1354 SetValueImpl (val, j);
1357 void double_swapper (int i, int j) {
1358 double[] array = this as double[];
1359 double val = array [i];
1360 array [i] = array [j];
1364 static int new_gap (int gap)
1366 gap = (gap * 10) / 13;
1367 if (gap == 9 || gap == 10)
1374 /* we use combsort because it's fast enough and very small, since we have
1375 * several specialized versions here.
1377 static void combsort (double[] array, int start, int size, Swapper swap_items)
1381 gap = new_gap (gap);
1382 bool swapped = false;
1383 int end = start + size - gap;
1384 for (int i = start; i < end; i++) {
1386 if (array [i] > array [j]) {
1387 double val = array [i];
1388 array [i] = array [j];
1391 if (swap_items != null)
1395 if (gap == 1 && !swapped)
1400 static void combsort (int[] array, int start, int size, Swapper swap_items)
1404 gap = new_gap (gap);
1405 bool swapped = false;
1406 int end = start + size - gap;
1407 for (int i = start; i < end; i++) {
1409 if (array [i] > array [j]) {
1410 int val = array [i];
1411 array [i] = array [j];
1414 if (swap_items != null)
1418 if (gap == 1 && !swapped)
1423 static void combsort (char[] array, int start, int size, Swapper swap_items)
1427 gap = new_gap (gap);
1428 bool swapped = false;
1429 int end = start + size - gap;
1430 for (int i = start; i < end; i++) {
1432 if (array [i] > array [j]) {
1433 char val = array [i];
1434 array [i] = array [j];
1437 if (swap_items != null)
1441 if (gap == 1 && !swapped)
1446 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1454 object objPivot = keys.GetValueImpl ((low + high) / 2);
1456 while (low <= high) {
1457 // Move the walls in
1458 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1460 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1464 swap (keys, items, low, high);
1471 qsort (keys, items, low0, high, comparer);
1473 qsort (keys, items, low, high0, comparer);
1476 private static void swap (Array keys, Array items, int i, int j)
1480 tmp = keys.GetValueImpl (i);
1481 keys.SetValueImpl (keys.GetValue (j), i);
1482 keys.SetValueImpl (tmp, j);
1484 if (items != null) {
1485 tmp = items.GetValueImpl (i);
1486 items.SetValueImpl (items.GetValueImpl (j), i);
1487 items.SetValueImpl (tmp, j);
1491 private static int compare (object value1, object value2, IComparer comparer)
1494 return value2 == null ? 0 : -1;
1495 else if (value2 == null)
1497 else if (comparer == null)
1498 return ((IComparable) value1).CompareTo (value2);
1500 return comparer.Compare (value1, value2);
1504 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1505 public static void Sort<T> (T [] array)
1508 throw new ArgumentNullException ("array");
1510 Sort<T, T> (array, null, 0, array.Length, null);
1513 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1514 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items)
1517 throw new ArgumentNullException ("keys");
1519 Sort<TKey, TValue> (keys, items, 0, keys.Length, null);
1522 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1523 public static void Sort<T> (T [] array, IComparer<T> comparer)
1526 throw new ArgumentNullException ("array");
1528 Sort<T, T> (array, null, 0, array.Length, comparer);
1531 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1532 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, IComparer<TKey> comparer)
1535 throw new ArgumentNullException ("keys");
1537 Sort<TKey, TValue> (keys, items, 0, keys.Length, comparer);
1540 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1541 public static void Sort<T> (T [] array, int index, int length)
1544 throw new ArgumentNullException ("array");
1546 Sort<T, T> (array, null, index, length, null);
1549 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1550 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length)
1552 Sort<TKey, TValue> (keys, items, index, length, null);
1555 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1556 public static void Sort<T> (T [] array, int index, int length, IComparer<T> comparer)
1559 throw new ArgumentNullException ("array");
1561 Sort<T, T> (array, null, index, length, comparer);
1564 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1565 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length, IComparer<TKey> comparer)
1568 throw new ArgumentNullException ("keys");
1571 throw new ArgumentOutOfRangeException ("index");
1574 throw new ArgumentOutOfRangeException ("length");
1576 if (keys.Length - index < length
1577 || (items != null && index > items.Length - length))
1578 throw new ArgumentException ();
1584 // Check for value types which can be sorted without Compare () method
1586 if (comparer == null) {
1591 iswapper = get_swapper<TValue> (items);
1592 if (keys is double[]) {
1593 combsort (keys as double[], index, length, iswapper);
1596 if (keys is int[]) {
1597 combsort (keys as int[], index, length, iswapper);
1600 if (keys is char[]) {
1601 combsort (keys as char[], index, length, iswapper);
1605 // Use Comparer<T>.Default instead
1606 // comparer = Comparer<K>.Default;
1611 int high0 = index + length - 1;
1612 qsort<TKey, TValue> (keys, items, low0, high0, comparer);
1614 catch (Exception e) {
1615 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1619 public static void Sort<T> (T [] array, Comparison<T> comparison)
1622 throw new ArgumentNullException ("array");
1623 Sort<T> (array, array.Length, comparison);
1626 internal static void Sort<T> (T [] array, int length, Comparison<T> comparison)
1628 if (comparison == null)
1629 throw new ArgumentNullException ("comparison");
1631 if (length <= 1 || array.Length <= 1)
1636 int high0 = length - 1;
1637 qsort<T> (array, low0, high0, comparison);
1639 catch (Exception e) {
1640 throw new InvalidOperationException (Locale.GetText ("Comparison threw an exception."), e);
1644 private static void qsort<K, V> (K [] keys, V [] items, int low0, int high0, IComparer<K> comparer)
1652 K keyPivot = keys [(low + high) / 2];
1654 while (low <= high) {
1655 // Move the walls in
1656 //while (low < high0 && comparer.Compare (keys [low], keyPivot) < 0)
1657 while (low < high0 && compare (keys [low], keyPivot, comparer) < 0)
1659 //while (high > low0 && comparer.Compare (keyPivot, keys [high]) < 0)
1660 while (high > low0 && compare (keyPivot, keys [high], comparer) < 0)
1664 swap<K, V> (keys, items, low, high);
1671 qsort<K, V> (keys, items, low0, high, comparer);
1673 qsort<K, V> (keys, items, low, high0, comparer);
1676 private static int compare<T> (T value1, T value2, IComparer<T> comparer)
1678 if (comparer != null)
1679 return comparer.Compare (value1, value2);
1680 else if (value1 == null)
1681 return value2 == null ? 0 : -1;
1682 else if (value2 == null)
1684 else if (value1 is IComparable<T>)
1685 return ((IComparable<T>) value1).CompareTo (value2);
1686 else if (value1 is IComparable)
1687 return ((IComparable) value1).CompareTo (value2);
1689 string msg = Locale.GetText ("No IComparable or IComparable<T> interface found for type '{0}'.");
1690 throw new InvalidOperationException (String.Format (msg, typeof (T)));
1693 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1701 T keyPivot = array [(low + high) / 2];
1703 while (low <= high) {
1704 // Move the walls in
1705 while (low < high0 && comparison (array [low], keyPivot) < 0)
1707 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1711 swap<T> (array, low, high);
1718 qsort<T> (array, low0, high, comparison);
1720 qsort<T> (array, low, high0, comparison);
1723 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1728 keys [i] = keys [j];
1731 if (items != null) {
1734 items [i] = items [j];
1739 private static void swap<T> (T [] array, int i, int j)
1742 array [i] = array [j];
1751 void CopyTo (Array array, int index)
1754 throw new ArgumentNullException ("array");
1756 // The order of these exception checks may look strange,
1757 // but that's how the microsoft runtime does it.
1759 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1760 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1761 throw new ArgumentException ();
1763 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1765 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1766 "Value has to be >= 0."));
1768 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1772 [ComVisible (false)]
1777 void CopyTo (Array array, long index)
1779 if (index < 0 || index > Int32.MaxValue)
1780 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1781 "Value must be >= 0 and <= Int32.MaxValue."));
1783 CopyTo (array, (int) index);
1787 internal class SimpleEnumerator : IEnumerator, ICloneable
1793 public SimpleEnumerator (Array arrayToEnumerate)
1795 this.enumeratee = arrayToEnumerate;
1796 this.currentpos = -1;
1797 this.length = arrayToEnumerate.Length;
1800 public object Current {
1802 // Exception messages based on MS implementation
1803 if (currentpos < 0 )
1804 throw new InvalidOperationException (Locale.GetText (
1805 "Enumeration has not started."));
1806 if (currentpos >= length)
1807 throw new InvalidOperationException (Locale.GetText (
1808 "Enumeration has already ended"));
1809 // Current should not increase the position. So no ++ over here.
1810 return enumeratee.GetValueImpl (currentpos);
1814 public bool MoveNext()
1816 //The docs say Current should throw an exception if last
1817 //call to MoveNext returned false. This means currentpos
1818 //should be set to length when returning false.
1819 if (currentpos < length)
1821 if(currentpos < length)
1832 public object Clone ()
1834 return MemberwiseClone ();
1839 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1840 public static void Resize<T> (ref T [] array, int newSize)
1842 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1845 internal static void Resize<T> (ref T[] array, int length, int newSize)
1848 throw new ArgumentOutOfRangeException ();
1850 if (array == null) {
1851 array = new T [newSize];
1855 if (array.Length == newSize)
1858 T [] a = new T [newSize];
1859 Array.Copy (array, a, Math.Min (newSize, length));
1863 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1866 throw new ArgumentNullException ("array");
1868 throw new ArgumentNullException ("match");
1870 foreach (T t in array)
1877 public static void ForEach<T> (T [] array, Action <T> action)
1880 throw new ArgumentNullException ("array");
1882 throw new ArgumentNullException ("action");
1884 foreach (T t in array)
1888 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1891 throw new ArgumentNullException ("array");
1892 if (converter == null)
1893 throw new ArgumentNullException ("converter");
1895 TOutput [] output = new TOutput [array.Length];
1896 for (int i = 0; i < array.Length; i ++)
1897 output [i] = converter (array [i]);
1902 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1905 throw new ArgumentNullException ("array");
1907 return FindLastIndex<T> (array, 0, array.Length, match);
1910 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1913 throw new ArgumentNullException ();
1915 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1918 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1921 throw new ArgumentNullException ("array");
1923 throw new ArgumentNullException ("match");
1925 if (startIndex > array.Length || startIndex + count > array.Length)
1926 throw new ArgumentOutOfRangeException ();
1928 for (int i = startIndex + count - 1; i >= startIndex; i--)
1929 if (match (array [i]))
1935 public static int FindIndex<T> (T [] array, Predicate<T> match)
1938 throw new ArgumentNullException ("array");
1940 return FindIndex<T> (array, 0, array.Length, match);
1943 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1946 throw new ArgumentNullException ("array");
1948 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1951 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1954 throw new ArgumentNullException ("array");
1957 throw new ArgumentNullException ("match");
1959 if (startIndex > array.Length || startIndex + count > array.Length)
1960 throw new ArgumentOutOfRangeException ();
1962 for (int i = startIndex; i < startIndex + count; i ++)
1963 if (match (array [i]))
1969 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1970 public static int BinarySearch<T> (T [] array, T value)
1973 throw new ArgumentNullException ("array");
1975 return BinarySearch<T> (array, 0, array.Length, value, null);
1978 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1979 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1982 throw new ArgumentNullException ("array");
1984 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1987 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1988 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1990 return BinarySearch<T> (array, offset, length, value, null);
1993 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1994 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1997 throw new ArgumentNullException ("array");
1999 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
2000 "index is less than the lower bound of array."));
2002 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
2003 "Value has to be >= 0."));
2004 // re-ordered to avoid possible integer overflow
2005 if (index > array.Length - length)
2006 throw new ArgumentException (Locale.GetText (
2007 "index and length do not specify a valid range in array."));
2008 if (comparer == null)
2009 comparer = Comparer <T>.Default;
2012 int iMax = index + length - 1;
2015 while (iMin <= iMax) {
2016 int iMid = (iMin + iMax) / 2;
2017 iCmp = comparer.Compare (value, array [iMid]);
2024 iMin = iMid + 1; // compensate for the rounding down
2026 } catch (Exception e) {
2027 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
2033 public static int IndexOf<T> (T [] array, T value)
2036 throw new ArgumentNullException ("array");
2038 return IndexOf<T> (array, value, 0, array.Length);
2041 public static int IndexOf<T> (T [] array, T value, int startIndex)
2044 throw new ArgumentNullException ("array");
2046 return IndexOf<T> (array, value, startIndex, array.Length - startIndex);
2049 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
2052 throw new ArgumentNullException ("array");
2054 // re-ordered to avoid possible integer overflow
2055 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
2056 throw new ArgumentOutOfRangeException ();
2058 int max = startIndex + count;
2059 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2060 for (int i = startIndex; i < max; i++) {
2061 if (equalityComparer.Equals (value, array [i]))
2068 public static int LastIndexOf<T> (T [] array, T value)
2071 throw new ArgumentNullException ("array");
2073 return LastIndexOf<T> (array, value, array.Length - 1);
2076 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
2079 throw new ArgumentNullException ("array");
2081 return LastIndexOf<T> (array, value, startIndex, startIndex + 1);
2084 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
2087 throw new ArgumentNullException ("array");
2089 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
2090 throw new ArgumentOutOfRangeException ();
2092 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2093 for (int i = startIndex; i >= startIndex - count + 1; i--) {
2094 if (equalityComparer.Equals (value, array [i]))
2101 public static T [] FindAll<T> (T [] array, Predicate <T> match)
2104 throw new ArgumentNullException ("array");
2107 throw new ArgumentNullException ("match");
2110 T [] d = new T [array.Length];
2111 foreach (T t in array)
2115 Resize <T> (ref d, pos);
2119 public static bool Exists<T> (T [] array, Predicate <T> match)
2122 throw new ArgumentNullException ("array");
2125 throw new ArgumentNullException ("match");
2127 foreach (T t in array)
2133 public static ReadOnlyCollection<T> AsReadOnly<T> (T[] array)
2136 throw new ArgumentNullException ("array");
2137 return new ReadOnlyCollection<T> (new ArrayReadOnlyList<T> (array));
2140 public static T Find<T> (T [] array, Predicate<T> match)
2143 throw new ArgumentNullException ("array");
2146 throw new ArgumentNullException ("match");
2148 foreach (T t in array)
2155 public static T FindLast<T> (T [] array, Predicate <T> match)
2158 throw new ArgumentNullException ("array");
2161 throw new ArgumentNullException ("match");
2163 for (int i = array.Length - 1; i >= 0; i--)
2164 if (match (array [i]))
2170 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
2172 // The constrained copy should guarantee that if there is an exception thrown
2173 // during the copy, the destination array remains unchanged.
2174 // This is related to System.Runtime.Reliability.CER
2175 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
2177 Copy (s, s_i, d, d_i, c);
2182 class ArrayReadOnlyList<T> : IList<T>
2187 public ArrayReadOnlyList (T [] array)
2190 is_value_type = typeof (T).IsValueType;
2193 public T this [int index] {
2195 if (unchecked ((uint) index) >= unchecked ((uint) array.Length))
2196 throw new ArgumentOutOfRangeException ("index");
2197 return array [index];
2199 set { throw ReadOnlyError (); }
2203 get { return array.Length; }
2206 public bool IsReadOnly {
2207 get { return true; }
2210 public void Add (T item)
2212 throw ReadOnlyError ();
2215 public void Clear ()
2217 throw ReadOnlyError ();
2220 public bool Contains (T item)
2222 return Array.IndexOf<T> (array, item) >= 0;
2225 public void CopyTo (T [] array, int index)
2227 array.CopyTo (array, index);
2230 IEnumerator IEnumerable.GetEnumerator ()
2232 return GetEnumerator ();
2235 public IEnumerator<T> GetEnumerator ()
2237 for (int i = 0; i < array.Length; i++)
2238 yield return array [i];
2241 public int IndexOf (T item)
2243 return Array.IndexOf<T> (array, item);
2246 public void Insert (int index, T item)
2248 throw ReadOnlyError ();
2251 public bool Remove (T item)
2253 throw ReadOnlyError ();
2256 public void RemoveAt (int index)
2258 throw ReadOnlyError ();
2261 Exception ReadOnlyError ()
2263 return new NotSupportedException ("This collection is read-only.");
2269 #if BOOTSTRAP_WITH_OLDLIB
2270 /* delegate used to swap array elements, keep defined outside Array */
2271 delegate void Swapper (int i, int j);