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 [MonoTODO ("We are doing way to many double/triple exception checks for the overloaded functions")]
47 [MonoTODO ("Sort overloads parameter checks are VERY inconsistent")]
48 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
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);
90 if (item.Equals (value))
97 protected void InternalArray__ICollection_CopyTo<T> (T[] array, int index)
100 throw new ArgumentNullException ("array");
102 // The order of these exception checks may look strange,
103 // but that's how the microsoft runtime does it.
105 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
106 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
107 throw new ArgumentException ();
109 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
111 throw new ArgumentOutOfRangeException (
112 "index", Locale.GetText ("Value has to be >= 0."));
114 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
117 protected void InternalArray__Insert<T> (int index, T item)
119 throw new NotSupportedException ("Collection is read-only");
122 protected void InternalArray__RemoveAt<T> (int index)
124 throw new NotSupportedException ("Collection is read-only");
127 protected int InternalArray__IndexOf<T> (T item)
130 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
132 int length = this.Length;
133 for (int i = 0; i < length; i++) {
135 GetGenericValueImpl (i, out value);
136 if (item.Equals (value))
137 // array index may not be zero-based.
139 return i + this.GetLowerBound (0);
144 // lower bound may be MinValue
145 retVal = this.GetLowerBound (0) - 1;
151 protected T InternalArray__get_Item<T> (int index)
153 if (unchecked ((uint) index) >= unchecked ((uint) Length))
154 throw new ArgumentOutOfRangeException ("index");
157 GetGenericValueImpl (index, out value);
161 protected void InternalArray__set_Item<T> (int index, T item)
163 throw new NotSupportedException ("Collection is read-only");
166 // CAUTION! No bounds checking!
167 [MethodImplAttribute (MethodImplOptions.InternalCall)]
168 internal extern void GetGenericValueImpl<T> (int pos, out T value);
170 internal struct InternalEnumerator<T> : IEnumerator<T>
172 const int NOT_STARTED = -2;
174 // this MUST be -1, because we depend on it in move next.
175 // we just decr the size, so, 0 - 1 == FINISHED
176 const int FINISHED = -1;
181 internal InternalEnumerator (Array array)
187 public void Dispose ()
192 public bool MoveNext ()
194 if (idx == NOT_STARTED)
197 return idx != FINISHED && -- idx != FINISHED;
203 throw new InvalidOperationException ();
205 return array.InternalArray__get_Item<T> (array.Length - 1 - idx);
209 void IEnumerator.Reset ()
211 throw new NotImplementedException ();
214 object IEnumerator.Current {
225 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
228 int length = this.GetLength (0);
230 for (int i = 1; i < this.Rank; i++) {
231 length *= this.GetLength (i);
239 public long LongLength {
241 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
243 get { return Length; }
249 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
252 return this.GetRank ();
257 object IList.this [int index] {
259 if (unchecked ((uint) index) >= unchecked ((uint) Length))
260 throw new ArgumentOutOfRangeException ("index");
261 return GetValueImpl (index);
264 if (unchecked ((uint) index) >= unchecked ((uint) Length))
265 throw new ArgumentOutOfRangeException ("index");
266 SetValueImpl (value, index);
270 int IList.Add (object value)
272 throw new NotSupportedException ();
277 Array.Clear (this, this.GetLowerBound (0), this.Length);
280 bool IList.Contains (object value)
283 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
285 int length = this.Length;
286 for (int i = 0; i < length; i++) {
287 if (Object.Equals (value, this.GetValueImpl (i)))
294 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
296 int IList.IndexOf (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)))
304 // array index may not be zero-based.
306 return i + this.GetLowerBound (0);
311 // lower bound may be MinValue
312 retVal = this.GetLowerBound (0) - 1;
318 void IList.Insert (int index, object value)
320 throw new NotSupportedException ();
323 void IList.Remove (object value)
325 throw new NotSupportedException ();
328 void IList.RemoveAt (int index)
330 throw new NotSupportedException ();
333 // InternalCall Methods
334 [MethodImplAttribute (MethodImplOptions.InternalCall)]
335 protected extern int GetRank ();
337 [MethodImplAttribute (MethodImplOptions.InternalCall)]
338 public extern int GetLength (int dimension);
342 public long GetLongLength (int dimension)
344 return GetLength (dimension);
349 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
351 [MethodImplAttribute (MethodImplOptions.InternalCall)]
352 public extern int GetLowerBound (int dimension);
354 [MethodImplAttribute (MethodImplOptions.InternalCall)]
355 public extern object GetValue (params int[] indices);
357 [MethodImplAttribute (MethodImplOptions.InternalCall)]
358 public extern void SetValue (object value, params int[] indices);
360 // CAUTION! No bounds checking!
361 [MethodImplAttribute (MethodImplOptions.InternalCall)]
362 internal extern object GetValueImpl (int pos);
364 // CAUTION! No bounds checking!
365 [MethodImplAttribute (MethodImplOptions.InternalCall)]
366 internal extern void SetValueImpl (object value, int pos);
368 [MethodImplAttribute (MethodImplOptions.InternalCall)]
369 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
371 [MethodImplAttribute (MethodImplOptions.InternalCall)]
372 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
375 int ICollection.Count {
385 bool IsSynchronized {
425 IEnumerator GetEnumerator ()
427 return new SimpleEnumerator (this);
431 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
433 public int GetUpperBound (int dimension)
435 return GetLowerBound (dimension) + GetLength (dimension) - 1;
438 public object GetValue (int index)
441 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
442 if (index < GetLowerBound (0) || index > GetUpperBound (0))
443 throw new IndexOutOfRangeException (Locale.GetText (
444 "Index has to be between upper and lower bound of the array."));
446 return GetValueImpl (index - GetLowerBound (0));
449 public object GetValue (int index1, int index2)
451 int[] ind = {index1, index2};
452 return GetValue (ind);
455 public object GetValue (int index1, int index2, int index3)
457 int[] ind = {index1, index2, index3};
458 return GetValue (ind);
463 public object GetValue (long index)
465 if (index < 0 || index > Int32.MaxValue)
466 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
467 "Value must be >= 0 and <= Int32.MaxValue."));
469 return GetValue ((int) index);
473 public object GetValue (long index1, long index2)
475 if (index1 < 0 || index1 > Int32.MaxValue)
476 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
477 "Value must be >= 0 and <= Int32.MaxValue."));
479 if (index2 < 0 || index2 > Int32.MaxValue)
480 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
481 "Value must be >= 0 and <= Int32.MaxValue."));
483 return GetValue ((int) index1, (int) index2);
487 public object GetValue (long index1, long index2, long index3)
489 if (index1 < 0 || index1 > Int32.MaxValue)
490 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
491 "Value must be >= 0 and <= Int32.MaxValue."));
493 if (index2 < 0 || index2 > Int32.MaxValue)
494 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
495 "Value must be >= 0 and <= Int32.MaxValue."));
497 if (index3 < 0 || index3 > Int32.MaxValue)
498 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
499 "Value must be >= 0 and <= Int32.MaxValue."));
501 return GetValue ((int) index1, (int) index2, (int) index3);
505 public void SetValue (object value, long index)
507 if (index < 0 || index > Int32.MaxValue)
508 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
509 "Value must be >= 0 and <= Int32.MaxValue."));
511 SetValue (value, (int) index);
515 public void SetValue (object value, long index1, long index2)
517 if (index1 < 0 || index1 > Int32.MaxValue)
518 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
519 "Value must be >= 0 and <= Int32.MaxValue."));
521 if (index2 < 0 || index2 > Int32.MaxValue)
522 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
523 "Value must be >= 0 and <= Int32.MaxValue."));
525 int[] ind = {(int) index1, (int) index2};
526 SetValue (value, ind);
530 public void SetValue (object value, long index1, long index2, long index3)
532 if (index1 < 0 || index1 > Int32.MaxValue)
533 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
534 "Value must be >= 0 and <= Int32.MaxValue."));
536 if (index2 < 0 || index2 > Int32.MaxValue)
537 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
538 "Value must be >= 0 and <= Int32.MaxValue."));
540 if (index3 < 0 || index3 > Int32.MaxValue)
541 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
542 "Value must be >= 0 and <= Int32.MaxValue."));
544 int[] ind = {(int) index1, (int) index2, (int) index3};
545 SetValue (value, ind);
549 public void SetValue (object value, int index)
552 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
553 if (index < GetLowerBound (0) || index > GetUpperBound (0))
554 throw new IndexOutOfRangeException (Locale.GetText (
555 "Index has to be >= lower bound and <= upper bound of the array."));
557 SetValueImpl (value, index - GetLowerBound (0));
560 public void SetValue (object value, int index1, int index2)
562 int[] ind = {index1, index2};
563 SetValue (value, ind);
566 public void SetValue (object value, int index1, int index2, int index3)
568 int[] ind = {index1, index2, index3};
569 SetValue (value, ind);
572 public static Array CreateInstance (Type elementType, int length)
574 int[] lengths = {length};
576 return CreateInstance (elementType, lengths);
579 public static Array CreateInstance (Type elementType, int length1, int length2)
581 int[] lengths = {length1, length2};
583 return CreateInstance (elementType, lengths);
586 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
588 int[] lengths = {length1, length2, length3};
590 return CreateInstance (elementType, lengths);
593 public static Array CreateInstance (Type elementType, int[] lengths)
595 if (elementType == null)
596 throw new ArgumentNullException ("elementType");
598 throw new ArgumentNullException ("lengths");
600 if (lengths.Length > 255)
601 throw new TypeLoadException ();
605 elementType = elementType.UnderlyingSystemType;
606 if (!elementType.IsSystemType)
607 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
609 return CreateInstanceImpl (elementType, lengths, bounds);
612 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
614 if (elementType == null)
615 throw new ArgumentNullException ("elementType");
617 throw new ArgumentNullException ("lengths");
619 throw new ArgumentNullException ("bounds");
621 elementType = elementType.UnderlyingSystemType;
622 if (!elementType.IsSystemType)
623 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
625 if (lengths.Length < 1)
626 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
628 if (lengths.Length != bounds.Length)
629 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
631 for (int j = 0; j < bounds.Length; j ++) {
633 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
634 "Each value has to be >= 0."));
635 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
636 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
637 "Length + bound must not exceed Int32.MaxValue."));
640 if (lengths.Length > 255)
641 throw new TypeLoadException ();
643 return CreateInstanceImpl (elementType, lengths, bounds);
647 static int [] GetIntArray (long [] values)
649 int len = values.Length;
650 int [] ints = new int [len];
651 for (int i = 0; i < len; i++) {
652 long current = values [i];
653 if (current < 0 || current > (long) Int32.MaxValue)
654 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
655 "Each value has to be >= 0 and <= Int32.MaxValue."));
657 ints [i] = (int) current;
662 public static Array CreateInstance (Type elementType, params long [] lengths)
666 throw new ArgumentNullException ("lengths");
668 return CreateInstance (elementType, GetIntArray (lengths));
672 public object GetValue (params long [] indices)
676 throw new ArgumentNullException ("indices");
678 return GetValue (GetIntArray (indices));
682 public void SetValue (object value, params long [] indices)
686 throw new ArgumentNullException ("indices");
688 SetValue (value, GetIntArray (indices));
693 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
695 public static int BinarySearch (Array array, object value)
698 throw new ArgumentNullException ("array");
704 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
706 if (array.Length == 0)
709 if (!(value is IComparable))
710 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
712 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
716 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
718 public static int BinarySearch (Array array, object value, IComparer comparer)
721 throw new ArgumentNullException ("array");
724 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
726 if (array.Length == 0)
729 if ((comparer == null) && (value != null) && !(value is IComparable))
730 throw new ArgumentException (Locale.GetText (
731 "comparer is null and value does not support IComparable."));
733 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
737 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
739 public static int BinarySearch (Array array, int index, int length, object value)
742 throw new ArgumentNullException ("array");
745 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
747 if (index < array.GetLowerBound (0))
748 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
749 "index is less than the lower bound of array."));
751 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
752 "Value has to be >= 0."));
753 // re-ordered to avoid possible integer overflow
754 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
755 throw new ArgumentException (Locale.GetText (
756 "index and length do not specify a valid range in array."));
758 if (array.Length == 0)
761 if ((value != null) && (!(value is IComparable)))
762 throw new ArgumentException (Locale.GetText (
763 "value does not support IComparable"));
765 return DoBinarySearch (array, index, length, value, null);
769 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
771 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
774 throw new ArgumentNullException ("array");
777 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
779 if (index < array.GetLowerBound (0))
780 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
781 "index is less than the lower bound of array."));
783 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
784 "Value has to be >= 0."));
785 // re-ordered to avoid possible integer overflow
786 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
787 throw new ArgumentException (Locale.GetText (
788 "index and length do not specify a valid range in array."));
790 if (array.Length == 0)
793 if ((comparer == null) && (value != null) && !(value is IComparable))
794 throw new ArgumentException (Locale.GetText (
795 "comparer is null and value does not support IComparable."));
797 return DoBinarySearch (array, index, length, value, comparer);
800 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
802 // cache this in case we need it
803 if (comparer == null)
804 comparer = Comparer.Default;
807 // Comment from Tum (tum@veridicus.com):
808 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
809 int iMax = index + length - 1;
812 while (iMin <= iMax) {
813 int iMid = (iMin + iMax) / 2;
814 object elt = array.GetValueImpl (iMid);
816 iCmp = comparer.Compare (elt, value);
823 iMin = iMid + 1; // compensate for the rounding down
826 catch (Exception e) {
827 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
834 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
836 public static void Clear (Array array, int index, int length)
839 throw new ArgumentNullException ("array");
841 throw new ArgumentOutOfRangeException ("length < 0");
843 int low = array.GetLowerBound (0);
845 throw new IndexOutOfRangeException ("index < lower bound");
848 // re-ordered to avoid possible integer overflow
849 if (index > array.Length - length)
850 throw new IndexOutOfRangeException ("index + length > size");
852 ClearInternal (array, index, length);
855 [MethodImplAttribute (MethodImplOptions.InternalCall)]
856 static extern void ClearInternal (Array a, int index, int count);
858 [MethodImplAttribute (MethodImplOptions.InternalCall)]
863 extern object Clone ();
866 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
868 public static void Copy (Array sourceArray, Array destinationArray, int length)
870 // need these checks here because we are going to use
871 // GetLowerBound() on source and dest.
872 if (sourceArray == null)
873 throw new ArgumentNullException ("sourceArray");
875 if (destinationArray == null)
876 throw new ArgumentNullException ("destinationArray");
878 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
879 destinationArray.GetLowerBound (0), length);
883 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
885 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
887 if (sourceArray == null)
888 throw new ArgumentNullException ("sourceArray");
890 if (destinationArray == null)
891 throw new ArgumentNullException ("destinationArray");
894 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
895 "Value has to be >= 0."));;
898 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
899 "Value has to be >= 0."));;
901 if (destinationIndex < 0)
902 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
903 "Value has to be >= 0."));;
905 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
908 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
909 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
911 // re-ordered to avoid possible integer overflow
912 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
913 throw new ArgumentException ("length");
915 if (sourceArray.Rank != destinationArray.Rank)
916 throw new RankException (Locale.GetText ("Arrays must be of same size."));
918 Type src_type = sourceArray.GetType ().GetElementType ();
919 Type dst_type = destinationArray.GetType ().GetElementType ();
921 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
922 for (int i = 0; i < length; i++) {
923 Object srcval = sourceArray.GetValueImpl (source_pos + i);
926 destinationArray.SetValueImpl (srcval, dest_pos + i);
928 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
929 (src_type.Equals (typeof (Object))))
930 throw new InvalidCastException ();
932 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
933 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
938 for (int i = length - 1; i >= 0; 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));
957 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
959 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
960 long destinationIndex, long length)
962 if (sourceArray == null)
963 throw new ArgumentNullException ("sourceArray");
965 if (destinationArray == null)
966 throw new ArgumentNullException ("destinationArray");
968 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
969 throw new ArgumentOutOfRangeException ("sourceIndex",
970 Locale.GetText ("Must be in the Int32 range."));
972 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
973 throw new ArgumentOutOfRangeException ("destinationIndex",
974 Locale.GetText ("Must be in the Int32 range."));
976 if (length < 0 || length > Int32.MaxValue)
977 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
978 "Value must be >= 0 and <= Int32.MaxValue."));
980 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
984 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
986 public static void Copy (Array sourceArray, Array destinationArray, long length)
988 if (length < 0 || length > Int32.MaxValue)
989 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
990 "Value must be >= 0 and <= Int32.MaxValue."));
992 Copy (sourceArray, destinationArray, (int) length);
997 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
999 public static int IndexOf (Array array, object value)
1002 throw new ArgumentNullException ("array");
1004 return IndexOf (array, value, 0, array.Length);
1008 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1010 public static int IndexOf (Array array, object value, int startIndex)
1013 throw new ArgumentNullException ("array");
1015 return IndexOf (array, value, startIndex, array.Length - startIndex);
1019 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1021 public static int IndexOf (Array array, object value, int startIndex, int count)
1024 throw new ArgumentNullException ("array");
1027 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1029 // re-ordered to avoid possible integer overflow
1030 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1031 throw new ArgumentOutOfRangeException ();
1033 int max = startIndex + count;
1034 for (int i = startIndex; i < max; i++) {
1035 if (Object.Equals (value, array.GetValueImpl (i)))
1039 return array.GetLowerBound (0) - 1;
1043 public void Initialize()
1045 //FIXME: We would like to find a compiler that uses
1046 // this method. It looks like this method do nothing
1047 // in C# so no exception is trown by the moment.
1051 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1053 public static int LastIndexOf (Array array, object value)
1056 throw new ArgumentNullException ("array");
1058 return LastIndexOf (array, value, array.Length - 1);
1062 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1064 public static int LastIndexOf (Array array, object value, int startIndex)
1067 throw new ArgumentNullException ("array");
1069 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
1073 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1075 public static int LastIndexOf (Array array, object value, int startIndex, int count)
1078 throw new ArgumentNullException ("array");
1081 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1083 if (count < 0 || startIndex < array.GetLowerBound (0) ||
1084 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
1085 throw new ArgumentOutOfRangeException ();
1087 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1088 if (Object.Equals (value, array.GetValueImpl (i)))
1092 return array.GetLowerBound (0) - 1;
1095 #if !BOOTSTRAP_WITH_OLDLIB
1096 /* delegate used to swap array elements */
1097 delegate void Swapper (int i, int j);
1100 static Swapper get_swapper (Array array)
1103 return new Swapper (array.int_swapper);
1104 if (array is double[])
1105 return new Swapper (array.double_swapper);
1106 if (array is object[]) {
1107 return new Swapper (array.obj_swapper);
1109 return new Swapper (array.slow_swapper);
1113 static Swapper get_swapper<T> (T [] array)
1116 return new Swapper (array.int_swapper);
1117 if (array is double[])
1118 return new Swapper (array.double_swapper);
1120 return new Swapper (array.obj_swapper);
1125 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1127 public static void Reverse (Array array)
1130 throw new ArgumentNullException ("array");
1132 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
1136 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1138 public static void Reverse (Array array, int index, int length)
1141 throw new ArgumentNullException ("array");
1144 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1146 if (index < array.GetLowerBound (0) || length < 0)
1147 throw new ArgumentOutOfRangeException ();
1149 // re-ordered to avoid possible integer overflow
1150 if (index > array.GetUpperBound (0) + 1 - length)
1151 throw new ArgumentException ();
1153 int end = index + length - 1;
1154 object[] oarray = array as object[];
1155 if (oarray != null) {
1156 while (index < end) {
1157 object tmp = oarray [index];
1158 oarray [index] = oarray [end];
1165 int[] iarray = array as int[];
1166 if (iarray != null) {
1167 while (index < end) {
1168 int tmp = iarray [index];
1169 iarray [index] = iarray [end];
1176 double[] darray = array as double[];
1177 if (darray != null) {
1178 while (index < end) {
1179 double tmp = darray [index];
1180 darray [index] = darray [end];
1188 Swapper swapper = get_swapper (array);
1189 while (index < end) {
1190 swapper (index, end);
1197 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1199 public static void Sort (Array array)
1202 throw new ArgumentNullException ("array");
1204 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
1208 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1210 public static void Sort (Array keys, Array items)
1213 throw new ArgumentNullException ("keys");
1215 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1219 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1221 public static void Sort (Array array, IComparer comparer)
1224 throw new ArgumentNullException ("array");
1226 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1230 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1232 public static void Sort (Array array, int index, int length)
1234 Sort (array, null, index, length, null);
1238 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1240 public static void Sort (Array keys, Array items, IComparer comparer)
1243 throw new ArgumentNullException ("keys");
1245 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1249 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1251 public static void Sort (Array keys, Array items, int index, int length)
1253 Sort (keys, items, index, length, null);
1257 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1259 public static void Sort (Array array, int index, int length, IComparer comparer)
1261 Sort (array, null, index, length, comparer);
1265 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1268 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1271 throw new ArgumentNullException ("keys");
1273 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1274 throw new RankException ();
1276 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1277 throw new ArgumentException ();
1279 if (index < keys.GetLowerBound (0))
1280 throw new ArgumentOutOfRangeException ("index");
1283 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1284 "Value has to be >= 0."));
1286 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1287 throw new ArgumentException ();
1292 if (comparer == null) {
1297 iswapper = get_swapper (items);
1298 if (keys is double[]) {
1299 combsort (keys as double[], index, length, iswapper);
1302 if (keys is int[]) {
1303 combsort (keys as int[], index, length, iswapper);
1306 if (keys is char[]) {
1307 combsort (keys as char[], index, length, iswapper);
1313 int high0 = index + length - 1;
1314 qsort (keys, items, low0, high0, comparer);
1316 catch (Exception e) {
1317 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1321 /* note, these are instance methods */
1322 void int_swapper (int i, int j) {
1323 int[] array = this as int[];
1324 int val = array [i];
1325 array [i] = array [j];
1329 void obj_swapper (int i, int j) {
1330 object[] array = this as object[];
1331 object val = array [i];
1332 array [i] = array [j];
1336 void slow_swapper (int i, int j) {
1337 object val = GetValueImpl (i);
1338 SetValueImpl (GetValue (j), i);
1339 SetValueImpl (val, j);
1342 void double_swapper (int i, int j) {
1343 double[] array = this as double[];
1344 double val = array [i];
1345 array [i] = array [j];
1349 static int new_gap (int gap)
1351 gap = (gap * 10) / 13;
1352 if (gap == 9 || gap == 10)
1359 /* we use combsort because it's fast enough and very small, since we have
1360 * several specialized versions here.
1362 static void combsort (double[] array, int start, int size, Swapper swap_items)
1366 gap = new_gap (gap);
1367 bool swapped = false;
1368 int end = start + size - gap;
1369 for (int i = start; i < end; i++) {
1371 if (array [i] > array [j]) {
1372 double val = array [i];
1373 array [i] = array [j];
1376 if (swap_items != null)
1380 if (gap == 1 && !swapped)
1385 static void combsort (int[] array, int start, int size, Swapper swap_items)
1389 gap = new_gap (gap);
1390 bool swapped = false;
1391 int end = start + size - gap;
1392 for (int i = start; i < end; i++) {
1394 if (array [i] > array [j]) {
1395 int val = array [i];
1396 array [i] = array [j];
1399 if (swap_items != null)
1403 if (gap == 1 && !swapped)
1408 static void combsort (char[] array, int start, int size, Swapper swap_items)
1412 gap = new_gap (gap);
1413 bool swapped = false;
1414 int end = start + size - gap;
1415 for (int i = start; i < end; i++) {
1417 if (array [i] > array [j]) {
1418 char val = array [i];
1419 array [i] = array [j];
1422 if (swap_items != null)
1426 if (gap == 1 && !swapped)
1431 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1439 object objPivot = keys.GetValueImpl ((low + high) / 2);
1441 while (low <= high) {
1442 // Move the walls in
1443 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1445 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1449 swap (keys, items, low, high);
1456 qsort (keys, items, low0, high, comparer);
1458 qsort (keys, items, low, high0, comparer);
1461 private static void swap (Array keys, Array items, int i, int j)
1465 tmp = keys.GetValueImpl (i);
1466 keys.SetValueImpl (keys.GetValue (j), i);
1467 keys.SetValueImpl (tmp, j);
1469 if (items != null) {
1470 tmp = items.GetValueImpl (i);
1471 items.SetValueImpl (items.GetValueImpl (j), i);
1472 items.SetValueImpl (tmp, j);
1476 private static int compare (object value1, object value2, IComparer comparer)
1479 return value2 == null ? 0 : -1;
1480 else if (value2 == null)
1482 else if (comparer == null)
1483 return ((IComparable) value1).CompareTo (value2);
1485 return comparer.Compare (value1, value2);
1489 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1490 public static void Sort<T> (T [] array)
1493 throw new ArgumentNullException ("array");
1495 Sort<T, T> (array, null, 0, array.Length, null);
1498 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1499 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items)
1502 throw new ArgumentNullException ("keys");
1504 Sort<TKey, TValue> (keys, items, 0, keys.Length, null);
1507 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1508 public static void Sort<T> (T [] array, IComparer<T> comparer)
1511 throw new ArgumentNullException ("array");
1513 Sort<T, T> (array, null, 0, array.Length, comparer);
1516 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1517 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, IComparer<TKey> comparer)
1520 throw new ArgumentNullException ("keys");
1522 Sort<TKey, TValue> (keys, items, 0, keys.Length, comparer);
1525 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1526 public static void Sort<T> (T [] array, int index, int length)
1529 throw new ArgumentNullException ("array");
1531 Sort<T, T> (array, null, index, length, null);
1534 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1535 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length)
1537 Sort<TKey, TValue> (keys, items, index, length, null);
1540 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1541 public static void Sort<T> (T [] array, int index, int length, IComparer<T> comparer)
1544 throw new ArgumentNullException ("array");
1546 Sort<T, T> (array, null, index, length, comparer);
1549 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1550 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length, IComparer<TKey> comparer)
1553 throw new ArgumentNullException ("keys");
1556 throw new ArgumentOutOfRangeException ("index");
1559 throw new ArgumentOutOfRangeException ("length");
1561 if (keys.Length - index < length
1562 || (items != null && index > items.Length - length))
1563 throw new ArgumentException ();
1569 // Check for value types which can be sorted without Compare () method
1571 if (comparer == null) {
1576 iswapper = get_swapper<TValue> (items);
1577 if (keys is double[]) {
1578 combsort (keys as double[], index, length, iswapper);
1581 if (keys is int[]) {
1582 combsort (keys as int[], index, length, iswapper);
1585 if (keys is char[]) {
1586 combsort (keys as char[], index, length, iswapper);
1590 // Use Comparer<T>.Default instead
1591 // comparer = Comparer<K>.Default;
1596 int high0 = index + length - 1;
1597 qsort<TKey, TValue> (keys, items, low0, high0, comparer);
1599 catch (Exception e) {
1600 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1604 public static void Sort<T> (T [] array, Comparison<T> comparison)
1607 throw new ArgumentNullException ("array");
1608 Sort<T> (array, array.Length, comparison);
1611 internal static void Sort<T> (T [] array, int length, Comparison<T> comparison)
1613 if (comparison == null)
1614 throw new ArgumentNullException ("comparison");
1616 if (length <= 1 || array.Length <= 1)
1621 int high0 = length - 1;
1622 qsort<T> (array, low0, high0, comparison);
1624 catch (Exception e) {
1625 throw new InvalidOperationException (Locale.GetText ("Comparison threw an exception."), e);
1629 private static void qsort<K, V> (K [] keys, V [] items, int low0, int high0, IComparer<K> comparer)
1637 K keyPivot = keys [(low + high) / 2];
1639 while (low <= high) {
1640 // Move the walls in
1641 //while (low < high0 && comparer.Compare (keys [low], keyPivot) < 0)
1642 while (low < high0 && compare (keys [low], keyPivot, comparer) < 0)
1644 //while (high > low0 && comparer.Compare (keyPivot, keys [high]) < 0)
1645 while (high > low0 && compare (keyPivot, keys [high], comparer) < 0)
1649 swap<K, V> (keys, items, low, high);
1656 qsort<K, V> (keys, items, low0, high, comparer);
1658 qsort<K, V> (keys, items, low, high0, comparer);
1661 private static int compare<T> (T value1, T value2, IComparer<T> comparer)
1664 return value2 == null ? 0 : -1;
1665 else if (value2 == null)
1667 else if (value1 is IComparable<T>)
1668 return ((IComparable<T>) value1).CompareTo (value2);
1669 else if (value1 is IComparable)
1670 return ((IComparable) value1).CompareTo (value2);
1671 else if (comparer != null)
1672 return comparer.Compare (value1, value2);
1674 string msg = Locale.GetText ("No IComparable or IComparable<T> interface found for type '{0}'.");
1675 throw new InvalidOperationException (String.Format (msg, typeof (T)));
1678 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1686 T keyPivot = array [(low + high) / 2];
1688 while (low <= high) {
1689 // Move the walls in
1690 while (low < high0 && comparison (array [low], keyPivot) < 0)
1692 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1696 swap<T> (array, low, high);
1703 qsort<T> (array, low0, high, comparison);
1705 qsort<T> (array, low, high0, comparison);
1708 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1713 keys [i] = keys [j];
1716 if (items != null) {
1719 items [i] = items [j];
1724 private static void swap<T> (T [] array, int i, int j)
1727 array [i] = array [j];
1736 void CopyTo (Array array, int index)
1739 throw new ArgumentNullException ("array");
1741 // The order of these exception checks may look strange,
1742 // but that's how the microsoft runtime does it.
1744 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1745 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1746 throw new ArgumentException ();
1748 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1750 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1751 "Value has to be >= 0."));
1753 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1757 [ComVisible (false)]
1762 void CopyTo (Array array, long index)
1764 if (index < 0 || index > Int32.MaxValue)
1765 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1766 "Value must be >= 0 and <= Int32.MaxValue."));
1768 CopyTo (array, (int) index);
1772 internal class SimpleEnumerator : IEnumerator, ICloneable
1778 public SimpleEnumerator (Array arrayToEnumerate)
1780 this.enumeratee = arrayToEnumerate;
1781 this.currentpos = -1;
1782 this.length = arrayToEnumerate.Length;
1785 public object Current {
1787 // Exception messages based on MS implementation
1788 if (currentpos < 0 )
1789 throw new InvalidOperationException (Locale.GetText (
1790 "Enumeration has not started."));
1791 if (currentpos >= length)
1792 throw new InvalidOperationException (Locale.GetText (
1793 "Enumeration has already ended"));
1794 // Current should not increase the position. So no ++ over here.
1795 return enumeratee.GetValueImpl (currentpos);
1799 public bool MoveNext()
1801 //The docs say Current should throw an exception if last
1802 //call to MoveNext returned false. This means currentpos
1803 //should be set to length when returning false.
1804 if (currentpos < length)
1806 if(currentpos < length)
1817 public object Clone ()
1819 return MemberwiseClone ();
1824 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1825 public static void Resize<T> (ref T [] array, int newSize)
1827 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1830 internal static void Resize<T> (ref T[] array, int length, int newSize)
1833 throw new ArgumentOutOfRangeException ();
1835 if (array == null) {
1836 array = new T [newSize];
1840 if (array.Length == newSize)
1843 T [] a = new T [newSize];
1844 Array.Copy (array, a, Math.Min (newSize, length));
1848 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1851 throw new ArgumentNullException ("array");
1853 throw new ArgumentNullException ("match");
1855 foreach (T t in array)
1862 public static void ForEach<T> (T [] array, Action <T> action)
1865 throw new ArgumentNullException ("array");
1867 throw new ArgumentNullException ("action");
1869 foreach (T t in array)
1873 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1876 throw new ArgumentNullException ("array");
1877 if (converter == null)
1878 throw new ArgumentNullException ("converter");
1880 TOutput [] output = new TOutput [array.Length];
1881 for (int i = 0; i < array.Length; i ++)
1882 output [i] = converter (array [i]);
1887 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1890 throw new ArgumentNullException ("array");
1892 return FindLastIndex<T> (array, 0, array.Length, match);
1895 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1898 throw new ArgumentNullException ();
1900 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1903 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1906 throw new ArgumentNullException ("array");
1908 throw new ArgumentNullException ("match");
1910 if (startIndex > array.Length || startIndex + count > array.Length)
1911 throw new ArgumentOutOfRangeException ();
1913 for (int i = startIndex + count - 1; i >= startIndex; i--)
1914 if (match (array [i]))
1920 public static int FindIndex<T> (T [] array, Predicate<T> match)
1923 throw new ArgumentNullException ("array");
1925 return FindIndex<T> (array, 0, array.Length, match);
1928 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1931 throw new ArgumentNullException ("array");
1933 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1936 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1939 throw new ArgumentNullException ("array");
1942 throw new ArgumentNullException ("match");
1944 if (startIndex > array.Length || startIndex + count > array.Length)
1945 throw new ArgumentOutOfRangeException ();
1947 for (int i = startIndex; i < startIndex + count; i ++)
1948 if (match (array [i]))
1954 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1955 public static int BinarySearch<T> (T [] array, T value)
1958 throw new ArgumentNullException ("array");
1960 return BinarySearch<T> (array, 0, array.Length, value, null);
1963 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1964 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1967 throw new ArgumentNullException ("array");
1969 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1972 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1973 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1975 return BinarySearch<T> (array, offset, length, value, null);
1978 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1979 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1982 throw new ArgumentNullException ("array");
1984 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1985 "index is less than the lower bound of array."));
1987 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1988 "Value has to be >= 0."));
1989 // re-ordered to avoid possible integer overflow
1990 if (index > array.Length - length)
1991 throw new ArgumentException (Locale.GetText (
1992 "index and length do not specify a valid range in array."));
1993 if (comparer == null)
1994 comparer = Comparer <T>.Default;
1997 int iMax = index + length - 1;
2000 while (iMin <= iMax) {
2001 int iMid = (iMin + iMax) / 2;
2002 iCmp = comparer.Compare (value, array [iMid]);
2009 iMin = iMid + 1; // compensate for the rounding down
2011 } catch (Exception e) {
2012 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
2018 public static int IndexOf<T> (T [] array, T value)
2021 throw new ArgumentNullException ("array");
2023 return IndexOf<T> (array, value, 0, array.Length);
2026 public static int IndexOf<T> (T [] array, T value, int startIndex)
2029 throw new ArgumentNullException ("array");
2031 return IndexOf<T> (array, value, startIndex, array.Length - startIndex);
2034 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
2037 throw new ArgumentNullException ("array");
2039 // re-ordered to avoid possible integer overflow
2040 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
2041 throw new ArgumentOutOfRangeException ();
2043 int max = startIndex + count;
2044 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2045 for (int i = startIndex; i < max; i++) {
2046 if (equalityComparer.Equals (value, array [i]))
2053 public static int LastIndexOf<T> (T [] array, T value)
2056 throw new ArgumentNullException ("array");
2058 return LastIndexOf<T> (array, value, array.Length - 1);
2061 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
2064 throw new ArgumentNullException ("array");
2066 return LastIndexOf<T> (array, value, startIndex, startIndex + 1);
2069 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
2072 throw new ArgumentNullException ("array");
2074 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
2075 throw new ArgumentOutOfRangeException ();
2077 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
2078 for (int i = startIndex; i >= startIndex - count + 1; i--) {
2079 if (equalityComparer.Equals (value, array [i]))
2086 public static T [] FindAll<T> (T [] array, Predicate <T> match)
2089 throw new ArgumentNullException ("array");
2092 throw new ArgumentNullException ("match");
2095 T [] d = new T [array.Length];
2096 foreach (T t in array)
2100 Resize <T> (ref d, pos);
2104 public static bool Exists<T> (T [] array, Predicate <T> match)
2107 throw new ArgumentNullException ("array");
2110 throw new ArgumentNullException ("match");
2112 foreach (T t in array)
2118 public static ReadOnlyCollection<T> AsReadOnly<T> (T[] array)
2121 throw new ArgumentNullException ("array");
2122 return new ReadOnlyCollection<T> (new ArrayReadOnlyList<T> (array));
2125 public static T Find<T> (T [] array, Predicate<T> match)
2128 throw new ArgumentNullException ("array");
2131 throw new ArgumentNullException ("match");
2133 foreach (T t in array)
2140 public static T FindLast<T> (T [] array, Predicate <T> match)
2143 throw new ArgumentNullException ("array");
2146 throw new ArgumentNullException ("match");
2148 for (int i = array.Length - 1; i >= 0; i--)
2149 if (match (array [i]))
2155 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
2157 // The constrained copy should guarantee that if there is an exception thrown
2158 // during the copy, the destination array remains unchanged.
2159 // This is related to System.Runtime.Reliability.CER
2160 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
2162 Copy (s, s_i, d, d_i, c);
2167 class ArrayReadOnlyList<T> : IList<T>
2172 public ArrayReadOnlyList (T [] array)
2175 is_value_type = typeof (T).IsValueType;
2178 public T this [int index] {
2180 if (unchecked ((uint) index) >= unchecked ((uint) array.Length))
2181 throw new ArgumentOutOfRangeException ("index");
2182 return array [index];
2184 set { throw ReadOnlyError (); }
2188 get { return array.Length; }
2191 public bool IsReadOnly {
2192 get { return true; }
2195 public void Add (T item)
2197 throw ReadOnlyError ();
2200 public void Clear ()
2202 throw ReadOnlyError ();
2205 public bool Contains (T item)
2207 return Array.IndexOf<T> (array, item) >= 0;
2210 public void CopyTo (T [] array, int index)
2212 array.CopyTo (array, index);
2215 IEnumerator IEnumerable.GetEnumerator ()
2217 return GetEnumerator ();
2220 public IEnumerator<T> GetEnumerator ()
2222 for (int i = 0; i < array.Length; i++)
2223 yield return array [i];
2226 public int IndexOf (T item)
2228 return Array.IndexOf<T> (array, item);
2231 public void Insert (int index, T item)
2233 throw ReadOnlyError ();
2236 public bool Remove (T item)
2238 throw ReadOnlyError ();
2241 public void RemoveAt (int index)
2243 throw ReadOnlyError ();
2246 Exception ReadOnlyError ()
2248 return new NotSupportedException ("This collection is read-only.");
2254 #if BOOTSTRAP_WITH_OLDLIB
2255 /* delegate used to swap array elements, keep defined outside Array */
2256 delegate void Swapper (int i, int j);