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;
47 [MonoTODO ("We are doing way to many double/triple exception checks for the overloaded functions")]
48 [MonoTODO ("Sort overloads parameter checks are VERY inconsistent")]
49 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
59 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
62 int length = this.GetLength (0);
64 for (int i = 1; i < this.Rank; i++) {
65 length *= this.GetLength (i);
73 public long LongLength {
75 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
77 get { return Length; }
83 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
86 return this.GetRank ();
91 object IList.this [int index] {
93 if (unchecked ((uint) index) >= unchecked ((uint) Length))
94 throw new ArgumentOutOfRangeException ("index");
95 return GetValueImpl (index);
98 if (unchecked ((uint) index) >= unchecked ((uint) Length))
99 throw new ArgumentOutOfRangeException ("index");
100 SetValueImpl (value, index);
104 int IList.Add (object value)
106 throw new NotSupportedException ();
111 Array.Clear (this, this.GetLowerBound (0), this.Length);
114 bool IList.Contains (object value)
117 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
119 int length = this.Length;
120 for (int i = 0; i < length; i++) {
121 if (Object.Equals (value, this.GetValueImpl (i)))
128 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
130 int IList.IndexOf (object value)
133 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
135 int length = this.Length;
136 for (int i = 0; i < length; i++) {
137 if (Object.Equals (value, this.GetValueImpl (i)))
138 // array index may not be zero-based.
140 return i + this.GetLowerBound (0);
145 // lower bound may be MinValue
146 retVal = this.GetLowerBound (0) - 1;
152 void IList.Insert (int index, object value)
154 throw new NotSupportedException ();
157 void IList.Remove (object value)
159 throw new NotSupportedException ();
162 void IList.RemoveAt (int index)
164 throw new NotSupportedException ();
167 // InternalCall Methods
168 [MethodImplAttribute (MethodImplOptions.InternalCall)]
169 private extern int GetRank ();
171 [MethodImplAttribute (MethodImplOptions.InternalCall)]
172 public extern int GetLength (int dimension);
176 public long GetLongLength (int dimension)
178 return GetLength (dimension);
183 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
185 [MethodImplAttribute (MethodImplOptions.InternalCall)]
186 public extern int GetLowerBound (int dimension);
188 [MethodImplAttribute (MethodImplOptions.InternalCall)]
189 public extern object GetValue (params int[] indices);
191 [MethodImplAttribute (MethodImplOptions.InternalCall)]
192 public extern void SetValue (object value, params int[] indices);
194 // CAUTION! No bounds checking!
195 [MethodImplAttribute (MethodImplOptions.InternalCall)]
196 internal extern object GetValueImpl (int pos);
198 // CAUTION! No bounds checking!
199 [MethodImplAttribute (MethodImplOptions.InternalCall)]
200 internal extern void SetValueImpl (object value, int pos);
202 [MethodImplAttribute (MethodImplOptions.InternalCall)]
203 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
205 [MethodImplAttribute (MethodImplOptions.InternalCall)]
206 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
209 int ICollection.Count {
219 bool IsSynchronized {
259 IEnumerator GetEnumerator ()
261 return new SimpleEnumerator (this);
265 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
267 public int GetUpperBound (int dimension)
269 return GetLowerBound (dimension) + GetLength (dimension) - 1;
272 public object GetValue (int index)
275 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
276 if (index < GetLowerBound (0) || index > GetUpperBound (0))
277 throw new IndexOutOfRangeException (Locale.GetText (
278 "Index has to be between upper and lower bound of the array."));
280 return GetValueImpl (index - GetLowerBound (0));
283 public object GetValue (int index1, int index2)
285 int[] ind = {index1, index2};
286 return GetValue (ind);
289 public object GetValue (int index1, int index2, int index3)
291 int[] ind = {index1, index2, index3};
292 return GetValue (ind);
297 public object GetValue (long index)
299 if (index < 0 || index > Int32.MaxValue)
300 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
301 "Value must be >= 0 and <= Int32.MaxValue."));
303 return GetValue ((int) index);
307 public object GetValue (long index1, long index2)
309 if (index1 < 0 || index1 > Int32.MaxValue)
310 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
311 "Value must be >= 0 and <= Int32.MaxValue."));
313 if (index2 < 0 || index2 > Int32.MaxValue)
314 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
315 "Value must be >= 0 and <= Int32.MaxValue."));
317 return GetValue ((int) index1, (int) index2);
321 public object GetValue (long index1, long index2, long index3)
323 if (index1 < 0 || index1 > Int32.MaxValue)
324 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
325 "Value must be >= 0 and <= Int32.MaxValue."));
327 if (index2 < 0 || index2 > Int32.MaxValue)
328 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
329 "Value must be >= 0 and <= Int32.MaxValue."));
331 if (index3 < 0 || index3 > Int32.MaxValue)
332 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
333 "Value must be >= 0 and <= Int32.MaxValue."));
335 return GetValue ((int) index1, (int) index2, (int) index3);
339 public void SetValue (object value, long index)
341 if (index < 0 || index > Int32.MaxValue)
342 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
343 "Value must be >= 0 and <= Int32.MaxValue."));
345 SetValue (value, (int) index);
349 public void SetValue (object value, long index1, long index2)
351 if (index1 < 0 || index1 > Int32.MaxValue)
352 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
353 "Value must be >= 0 and <= Int32.MaxValue."));
355 if (index2 < 0 || index2 > Int32.MaxValue)
356 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
357 "Value must be >= 0 and <= Int32.MaxValue."));
359 int[] ind = {(int) index1, (int) index2};
360 SetValue (value, ind);
364 public void SetValue (object value, long index1, long index2, long index3)
366 if (index1 < 0 || index1 > Int32.MaxValue)
367 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
368 "Value must be >= 0 and <= Int32.MaxValue."));
370 if (index2 < 0 || index2 > Int32.MaxValue)
371 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
372 "Value must be >= 0 and <= Int32.MaxValue."));
374 if (index3 < 0 || index3 > Int32.MaxValue)
375 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
376 "Value must be >= 0 and <= Int32.MaxValue."));
378 int[] ind = {(int) index1, (int) index2, (int) index3};
379 SetValue (value, ind);
383 public void SetValue (object value, int index)
386 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
387 if (index < GetLowerBound (0) || index > GetUpperBound (0))
388 throw new IndexOutOfRangeException (Locale.GetText (
389 "Index has to be >= lower bound and <= upper bound of the array."));
391 SetValueImpl (value, index - GetLowerBound (0));
394 public void SetValue (object value, int index1, int index2)
396 int[] ind = {index1, index2};
397 SetValue (value, ind);
400 public void SetValue (object value, int index1, int index2, int index3)
402 int[] ind = {index1, index2, index3};
403 SetValue (value, ind);
406 public static Array CreateInstance (Type elementType, int length)
408 int[] lengths = {length};
410 return CreateInstance (elementType, lengths);
413 public static Array CreateInstance (Type elementType, int length1, int length2)
415 int[] lengths = {length1, length2};
417 return CreateInstance (elementType, lengths);
420 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
422 int[] lengths = {length1, length2, length3};
424 return CreateInstance (elementType, lengths);
427 public static Array CreateInstance (Type elementType, int[] lengths)
429 if (elementType == null)
430 throw new ArgumentNullException ("elementType");
432 throw new ArgumentNullException ("lengths");
434 if (lengths.Length > 255)
435 throw new TypeLoadException ();
439 elementType = elementType.UnderlyingSystemType;
440 if (!elementType.IsSystemType)
441 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
443 return CreateInstanceImpl (elementType, lengths, bounds);
446 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
448 if (elementType == null)
449 throw new ArgumentNullException ("elementType");
451 throw new ArgumentNullException ("lengths");
453 throw new ArgumentNullException ("bounds");
455 elementType = elementType.UnderlyingSystemType;
456 if (!elementType.IsSystemType)
457 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
459 if (lengths.Length < 1)
460 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
462 if (lengths.Length != bounds.Length)
463 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
465 for (int j = 0; j < bounds.Length; j ++) {
467 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
468 "Each value has to be >= 0."));
469 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
470 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
471 "Length + bound must not exceed Int32.MaxValue."));
474 if (lengths.Length > 255)
475 throw new TypeLoadException ();
477 return CreateInstanceImpl (elementType, lengths, bounds);
481 static int [] GetIntArray (long [] values)
483 int len = values.Length;
484 int [] ints = new int [len];
485 for (int i = 0; i < len; i++) {
486 long current = values [i];
487 if (current < 0 || current > (long) Int32.MaxValue)
488 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
489 "Each value has to be >= 0 and <= Int32.MaxValue."));
491 ints [i] = (int) current;
496 public static Array CreateInstance (Type elementType, params long [] lengths)
500 throw new ArgumentNullException ("lengths");
502 return CreateInstance (elementType, GetIntArray (lengths));
506 public object GetValue (params long [] indices)
510 throw new ArgumentNullException ("indices");
512 return GetValue (GetIntArray (indices));
516 public void SetValue (object value, params long [] indices)
520 throw new ArgumentNullException ("indices");
522 SetValue (value, GetIntArray (indices));
527 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
529 public static int BinarySearch (Array array, object value)
532 throw new ArgumentNullException ("array");
538 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
540 if (array.Length == 0)
543 if (!(value is IComparable))
544 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
546 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
550 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
552 public static int BinarySearch (Array array, object value, IComparer comparer)
555 throw new ArgumentNullException ("array");
558 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
560 if (array.Length == 0)
563 if ((comparer == null) && (value != null) && !(value is IComparable))
564 throw new ArgumentException (Locale.GetText (
565 "comparer is null and value does not support IComparable."));
567 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
571 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
573 public static int BinarySearch (Array array, int index, int length, object value)
576 throw new ArgumentNullException ("array");
579 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
581 if (index < array.GetLowerBound (0))
582 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
583 "index is less than the lower bound of array."));
585 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
586 "Value has to be >= 0."));
587 // re-ordered to avoid possible integer overflow
588 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
589 throw new ArgumentException (Locale.GetText (
590 "index and length do not specify a valid range in array."));
592 if (array.Length == 0)
595 if ((value != null) && (!(value is IComparable)))
596 throw new ArgumentException (Locale.GetText (
597 "value does not support IComparable"));
599 return DoBinarySearch (array, index, length, value, null);
603 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
605 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
608 throw new ArgumentNullException ("array");
611 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
613 if (index < array.GetLowerBound (0))
614 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
615 "index is less than the lower bound of array."));
617 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
618 "Value has to be >= 0."));
619 // re-ordered to avoid possible integer overflow
620 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
621 throw new ArgumentException (Locale.GetText (
622 "index and length do not specify a valid range in array."));
624 if (array.Length == 0)
627 if ((comparer == null) && (value != null) && !(value is IComparable))
628 throw new ArgumentException (Locale.GetText (
629 "comparer is null and value does not support IComparable."));
631 return DoBinarySearch (array, index, length, value, comparer);
634 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
636 // cache this in case we need it
637 if (comparer == null)
638 comparer = Comparer.Default;
641 // Comment from Tum (tum@veridicus.com):
642 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
643 int iMax = index + length - 1;
646 while (iMin <= iMax) {
647 int iMid = (iMin + iMax) / 2;
648 object elt = array.GetValueImpl (iMid);
650 iCmp = comparer.Compare (elt, value);
657 iMin = iMid + 1; // compensate for the rounding down
660 catch (Exception e) {
661 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
668 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
670 public static void Clear (Array array, int index, int length)
673 throw new ArgumentNullException ("array");
675 throw new ArgumentOutOfRangeException ("length < 0");
677 int low = array.GetLowerBound (0);
679 throw new IndexOutOfRangeException ("index < lower bound");
682 // re-ordered to avoid possible integer overflow
683 if (index > array.Length - length)
684 throw new IndexOutOfRangeException ("index + length > size");
686 ClearInternal (array, index, length);
689 [MethodImplAttribute (MethodImplOptions.InternalCall)]
690 static extern void ClearInternal (Array a, int index, int count);
692 [MethodImplAttribute (MethodImplOptions.InternalCall)]
697 extern object Clone ();
700 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
702 public static void Copy (Array sourceArray, Array destinationArray, int length)
704 // need these checks here because we are going to use
705 // GetLowerBound() on source and dest.
706 if (sourceArray == null)
707 throw new ArgumentNullException ("sourceArray");
709 if (destinationArray == null)
710 throw new ArgumentNullException ("destinationArray");
712 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
713 destinationArray.GetLowerBound (0), length);
717 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
719 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
721 if (sourceArray == null)
722 throw new ArgumentNullException ("sourceArray");
724 if (destinationArray == null)
725 throw new ArgumentNullException ("destinationArray");
728 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
729 "Value has to be >= 0."));;
732 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
733 "Value has to be >= 0."));;
735 if (destinationIndex < 0)
736 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
737 "Value has to be >= 0."));;
739 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
742 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
743 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
745 // re-ordered to avoid possible integer overflow
746 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
747 throw new ArgumentException ("length");
749 if (sourceArray.Rank != destinationArray.Rank)
750 throw new RankException (Locale.GetText ("Arrays must be of same size."));
752 Type src_type = sourceArray.GetType ().GetElementType ();
753 Type dst_type = destinationArray.GetType ().GetElementType ();
755 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
756 for (int i = 0; i < length; i++) {
757 Object srcval = sourceArray.GetValueImpl (source_pos + i);
760 destinationArray.SetValueImpl (srcval, dest_pos + i);
762 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
763 (src_type.Equals (typeof (Object))))
764 throw new InvalidCastException ();
766 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
767 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
772 for (int i = length - 1; i >= 0; i--) {
773 Object srcval = sourceArray.GetValueImpl (source_pos + i);
776 destinationArray.SetValueImpl (srcval, dest_pos + i);
778 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
779 (src_type.Equals (typeof (Object))))
780 throw new InvalidCastException ();
782 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
783 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
791 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
793 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
794 long destinationIndex, long length)
796 if (sourceArray == null)
797 throw new ArgumentNullException ("sourceArray");
799 if (destinationArray == null)
800 throw new ArgumentNullException ("destinationArray");
802 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
803 throw new ArgumentOutOfRangeException ("sourceIndex",
804 Locale.GetText ("Must be in the Int32 range."));
806 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
807 throw new ArgumentOutOfRangeException ("destinationIndex",
808 Locale.GetText ("Must be in the Int32 range."));
810 if (length < 0 || length > Int32.MaxValue)
811 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
812 "Value must be >= 0 and <= Int32.MaxValue."));
814 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
818 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
820 public static void Copy (Array sourceArray, Array destinationArray, long length)
822 if (length < 0 || length > Int32.MaxValue)
823 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
824 "Value must be >= 0 and <= Int32.MaxValue."));
826 Copy (sourceArray, destinationArray, (int) length);
831 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
833 public static int IndexOf (Array array, object value)
836 throw new ArgumentNullException ("array");
838 return IndexOf (array, value, 0, array.Length);
842 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
844 public static int IndexOf (Array array, object value, int startIndex)
847 throw new ArgumentNullException ("array");
849 return IndexOf (array, value, startIndex, array.Length - startIndex);
853 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
855 public static int IndexOf (Array array, object value, int startIndex, int count)
858 throw new ArgumentNullException ("array");
861 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
863 // re-ordered to avoid possible integer overflow
864 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
865 throw new ArgumentOutOfRangeException ();
867 int max = startIndex + count;
868 for (int i = startIndex; i < max; i++) {
869 if (Object.Equals (value, array.GetValueImpl (i)))
873 return array.GetLowerBound (0) - 1;
877 public void Initialize()
879 //FIXME: We would like to find a compiler that uses
880 // this method. It looks like this method do nothing
881 // in C# so no exception is trown by the moment.
885 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
887 public static int LastIndexOf (Array array, object value)
890 throw new ArgumentNullException ("array");
892 return LastIndexOf (array, value, array.Length - 1);
896 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
898 public static int LastIndexOf (Array array, object value, int startIndex)
901 throw new ArgumentNullException ("array");
903 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
907 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
909 public static int LastIndexOf (Array array, object value, int startIndex, int count)
912 throw new ArgumentNullException ("array");
915 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
917 if (count < 0 || startIndex < array.GetLowerBound (0) ||
918 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
919 throw new ArgumentOutOfRangeException ();
921 for (int i = startIndex; i >= startIndex - count + 1; i--) {
922 if (Object.Equals (value, array.GetValueImpl (i)))
926 return array.GetLowerBound (0) - 1;
929 #if !BOOTSTRAP_WITH_OLDLIB
930 /* delegate used to swap array elements */
931 delegate void Swapper (int i, int j);
934 static Swapper get_swapper (Array array)
937 return new Swapper (array.int_swapper);
938 if (array is double[])
939 return new Swapper (array.double_swapper);
940 if (array is object[]) {
941 return new Swapper (array.obj_swapper);
943 return new Swapper (array.slow_swapper);
947 static Swapper get_swapper<T> (T [] array)
950 return new Swapper (array.int_swapper);
951 if (array is double[])
952 return new Swapper (array.double_swapper);
954 return new Swapper (array.obj_swapper);
959 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
961 public static void Reverse (Array array)
964 throw new ArgumentNullException ("array");
966 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
970 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
972 public static void Reverse (Array array, int index, int length)
975 throw new ArgumentNullException ("array");
978 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
980 if (index < array.GetLowerBound (0) || length < 0)
981 throw new ArgumentOutOfRangeException ();
983 // re-ordered to avoid possible integer overflow
984 if (index > array.GetUpperBound (0) + 1 - length)
985 throw new ArgumentException ();
987 int end = index + length - 1;
988 object[] oarray = array as object[];
989 if (oarray != null) {
990 while (index < end) {
991 object tmp = oarray [index];
992 oarray [index] = oarray [end];
999 int[] iarray = array as int[];
1000 if (iarray != null) {
1001 while (index < end) {
1002 int tmp = iarray [index];
1003 iarray [index] = iarray [end];
1010 double[] darray = array as double[];
1011 if (darray != null) {
1012 while (index < end) {
1013 double tmp = darray [index];
1014 darray [index] = darray [end];
1022 Swapper swapper = get_swapper (array);
1023 while (index < end) {
1024 swapper (index, end);
1031 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1033 public static void Sort (Array array)
1036 throw new ArgumentNullException ("array");
1038 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
1042 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1044 public static void Sort (Array keys, Array items)
1047 throw new ArgumentNullException ("keys");
1049 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
1053 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1055 public static void Sort (Array array, IComparer comparer)
1058 throw new ArgumentNullException ("array");
1060 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
1064 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1066 public static void Sort (Array array, int index, int length)
1068 Sort (array, null, index, length, null);
1072 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1074 public static void Sort (Array keys, Array items, IComparer comparer)
1077 throw new ArgumentNullException ("keys");
1079 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
1083 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1085 public static void Sort (Array keys, Array items, int index, int length)
1087 Sort (keys, items, index, length, null);
1091 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1093 public static void Sort (Array array, int index, int length, IComparer comparer)
1095 Sort (array, null, index, length, comparer);
1099 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
1102 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
1105 throw new ArgumentNullException ("keys");
1107 if (keys.Rank > 1 || (items != null && items.Rank > 1))
1108 throw new RankException ();
1110 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
1111 throw new ArgumentException ();
1113 if (index < keys.GetLowerBound (0))
1114 throw new ArgumentOutOfRangeException ("index");
1117 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1118 "Value has to be >= 0."));
1120 if (keys.Length - (index + keys.GetLowerBound (0)) < length || (items != null && index > items.Length - length))
1121 throw new ArgumentException ();
1126 if (comparer == null) {
1131 iswapper = get_swapper (items);
1132 if (keys is double[]) {
1133 combsort (keys as double[], index, length, iswapper);
1136 if (keys is int[]) {
1137 combsort (keys as int[], index, length, iswapper);
1140 if (keys is char[]) {
1141 combsort (keys as char[], index, length, iswapper);
1147 int high0 = index + length - 1;
1148 qsort (keys, items, low0, high0, comparer);
1150 catch (Exception e) {
1151 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1155 /* note, these are instance methods */
1156 void int_swapper (int i, int j) {
1157 int[] array = this as int[];
1158 int val = array [i];
1159 array [i] = array [j];
1163 void obj_swapper (int i, int j) {
1164 object[] array = this as object[];
1165 object val = array [i];
1166 array [i] = array [j];
1170 void slow_swapper (int i, int j) {
1171 object val = GetValueImpl (i);
1172 SetValueImpl (GetValue (j), i);
1173 SetValueImpl (val, j);
1176 void double_swapper (int i, int j) {
1177 double[] array = this as double[];
1178 double val = array [i];
1179 array [i] = array [j];
1183 static int new_gap (int gap)
1185 gap = (gap * 10) / 13;
1186 if (gap == 9 || gap == 10)
1193 /* we use combsort because it's fast enough and very small, since we have
1194 * several specialized versions here.
1196 static void combsort (double[] array, int start, int size, Swapper swap_items)
1200 gap = new_gap (gap);
1201 bool swapped = false;
1202 int end = start + size - gap;
1203 for (int i = start; i < end; i++) {
1205 if (array [i] > array [j]) {
1206 double val = array [i];
1207 array [i] = array [j];
1210 if (swap_items != null)
1214 if (gap == 1 && !swapped)
1219 static void combsort (int[] array, int start, int size, Swapper swap_items)
1223 gap = new_gap (gap);
1224 bool swapped = false;
1225 int end = start + size - gap;
1226 for (int i = start; i < end; i++) {
1228 if (array [i] > array [j]) {
1229 int val = array [i];
1230 array [i] = array [j];
1233 if (swap_items != null)
1237 if (gap == 1 && !swapped)
1242 static void combsort (char[] array, int start, int size, Swapper swap_items)
1246 gap = new_gap (gap);
1247 bool swapped = false;
1248 int end = start + size - gap;
1249 for (int i = start; i < end; i++) {
1251 if (array [i] > array [j]) {
1252 char val = array [i];
1253 array [i] = array [j];
1256 if (swap_items != null)
1260 if (gap == 1 && !swapped)
1265 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
1273 object objPivot = keys.GetValueImpl ((low + high) / 2);
1275 while (low <= high) {
1276 // Move the walls in
1277 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
1279 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
1283 swap (keys, items, low, high);
1290 qsort (keys, items, low0, high, comparer);
1292 qsort (keys, items, low, high0, comparer);
1295 private static void swap (Array keys, Array items, int i, int j)
1299 tmp = keys.GetValueImpl (i);
1300 keys.SetValueImpl (keys.GetValue (j), i);
1301 keys.SetValueImpl (tmp, j);
1303 if (items != null) {
1304 tmp = items.GetValueImpl (i);
1305 items.SetValueImpl (items.GetValueImpl (j), i);
1306 items.SetValueImpl (tmp, j);
1310 private static int compare (object value1, object value2, IComparer comparer)
1313 return value2 == null ? 0 : -1;
1314 else if (value2 == null)
1316 else if (comparer == null)
1317 return ((IComparable) value1).CompareTo (value2);
1319 return comparer.Compare (value1, value2);
1323 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1324 public static void Sort<T> (T [] array)
1327 throw new ArgumentNullException ("array");
1329 Sort<T, T> (array, null, 0, array.Length, null);
1332 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1333 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items)
1336 throw new ArgumentNullException ("keys");
1338 Sort<TKey, TValue> (keys, items, 0, keys.Length, null);
1341 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1342 public static void Sort<T> (T [] array, IComparer<T> comparer)
1345 throw new ArgumentNullException ("array");
1347 Sort<T, T> (array, null, 0, array.Length, comparer);
1350 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1351 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, IComparer<TKey> comparer)
1354 throw new ArgumentNullException ("keys");
1356 Sort<TKey, TValue> (keys, items, 0, keys.Length, comparer);
1359 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1360 public static void Sort<T> (T [] array, int index, int length)
1363 throw new ArgumentNullException ("array");
1365 Sort<T, T> (array, null, index, length, null);
1368 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1369 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length)
1371 Sort<TKey, TValue> (keys, items, index, length, null);
1374 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1375 public static void Sort<T> (T [] array, int index, int length, IComparer<T> comparer)
1378 throw new ArgumentNullException ("array");
1380 Sort<T, T> (array, null, index, length, comparer);
1383 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1384 public static void Sort<TKey, TValue> (TKey [] keys, TValue [] items, int index, int length, IComparer<TKey> comparer)
1387 throw new ArgumentNullException ("keys");
1390 throw new ArgumentOutOfRangeException ("index");
1393 throw new ArgumentOutOfRangeException ("length");
1395 if (keys.Length - index < length
1396 || (items != null && index > items.Length - length))
1397 throw new ArgumentException ();
1403 // Check for value types which can be sorted without Compare () method
1405 if (comparer == null) {
1410 iswapper = get_swapper<TValue> (items);
1411 if (keys is double[]) {
1412 combsort (keys as double[], index, length, iswapper);
1415 if (keys is int[]) {
1416 combsort (keys as int[], index, length, iswapper);
1419 if (keys is char[]) {
1420 combsort (keys as char[], index, length, iswapper);
1424 // Use Comparer<T>.Default instead
1425 // comparer = Comparer<K>.Default;
1430 int high0 = index + length - 1;
1431 qsort<TKey, TValue> (keys, items, low0, high0, comparer);
1433 catch (Exception e) {
1434 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
1438 public static void Sort<T> (T [] array, Comparison<T> comparison)
1441 throw new ArgumentNullException ("array");
1442 Sort<T> (array, array.Length, comparison);
1445 internal static void Sort<T> (T [] array, int length, Comparison<T> comparison)
1447 if (comparison == null)
1448 throw new ArgumentNullException ("comparison");
1450 if (length <= 1 || array.Length <= 1)
1455 int high0 = length - 1;
1456 qsort<T> (array, low0, high0, comparison);
1458 catch (Exception e) {
1459 throw new InvalidOperationException (Locale.GetText ("Comparison threw an exception."), e);
1463 private static void qsort<K, V> (K [] keys, V [] items, int low0, int high0, IComparer<K> comparer)
1471 K keyPivot = keys [(low + high) / 2];
1473 while (low <= high) {
1474 // Move the walls in
1475 //while (low < high0 && comparer.Compare (keys [low], keyPivot) < 0)
1476 while (low < high0 && compare (keys [low], keyPivot, comparer) < 0)
1478 //while (high > low0 && comparer.Compare (keyPivot, keys [high]) < 0)
1479 while (high > low0 && compare (keyPivot, keys [high], comparer) < 0)
1483 swap<K, V> (keys, items, low, high);
1490 qsort<K, V> (keys, items, low0, high, comparer);
1492 qsort<K, V> (keys, items, low, high0, comparer);
1495 private static int compare<T> (T value1, T value2, IComparer<T> comparer)
1498 return value2 == null ? 0 : -1;
1499 else if (value2 == null)
1501 else if (value1 is IComparable<T>)
1502 return ((IComparable<T>) value1).CompareTo (value2);
1503 else if (value1 is IComparable)
1504 return ((IComparable) value1).CompareTo (value2);
1505 else if (comparer != null)
1506 return comparer.Compare (value1, value2);
1508 string msg = Locale.GetText ("No IComparable or IComparable<T> interface found for type '{0}'.");
1509 throw new InvalidOperationException (String.Format (msg, typeof (T)));
1512 private static void qsort<T> (T [] array, int low0, int high0, Comparison<T> comparison)
1520 T keyPivot = array [(low + high) / 2];
1522 while (low <= high) {
1523 // Move the walls in
1524 while (low < high0 && comparison (array [low], keyPivot) < 0)
1526 while (high > low0 && comparison (keyPivot, array [high]) < 0)
1530 swap<T> (array, low, high);
1537 qsort<T> (array, low0, high, comparison);
1539 qsort<T> (array, low, high0, comparison);
1542 private static void swap<K, V> (K [] keys, V [] items, int i, int j)
1547 keys [i] = keys [j];
1550 if (items != null) {
1553 items [i] = items [j];
1558 private static void swap<T> (T [] array, int i, int j)
1561 array [i] = array [j];
1570 void CopyTo (Array array, int index)
1573 throw new ArgumentNullException ("array");
1575 // The order of these exception checks may look strange,
1576 // but that's how the microsoft runtime does it.
1578 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1579 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1580 throw new ArgumentException ();
1582 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1584 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1585 "Value has to be >= 0."));
1587 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1591 [ComVisible (false)]
1596 void CopyTo (Array array, long index)
1598 if (index < 0 || index > Int32.MaxValue)
1599 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1600 "Value must be >= 0 and <= Int32.MaxValue."));
1602 CopyTo (array, (int) index);
1606 internal class SimpleEnumerator : IEnumerator, ICloneable
1612 public SimpleEnumerator (Array arrayToEnumerate)
1614 this.enumeratee = arrayToEnumerate;
1615 this.currentpos = -1;
1616 this.length = arrayToEnumerate.Length;
1619 public object Current {
1621 // Exception messages based on MS implementation
1622 if (currentpos < 0 )
1623 throw new InvalidOperationException (Locale.GetText (
1624 "Enumeration has not started."));
1625 if (currentpos >= length)
1626 throw new InvalidOperationException (Locale.GetText (
1627 "Enumeration has already ended"));
1628 // Current should not increase the position. So no ++ over here.
1629 return enumeratee.GetValueImpl (currentpos);
1633 public bool MoveNext()
1635 //The docs say Current should throw an exception if last
1636 //call to MoveNext returned false. This means currentpos
1637 //should be set to length when returning false.
1638 if (currentpos < length)
1640 if(currentpos < length)
1651 public object Clone ()
1653 return MemberwiseClone ();
1658 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1659 public static void Resize<T> (ref T [] array, int newSize)
1661 Resize<T> (ref array, array == null ? 0 : array.Length, newSize);
1664 internal static void Resize<T> (ref T[] array, int length, int newSize)
1667 throw new ArgumentOutOfRangeException ();
1669 if (array == null) {
1670 array = new T [newSize];
1674 if (array.Length == newSize)
1677 T [] a = new T [newSize];
1678 Array.Copy (array, a, Math.Min (newSize, length));
1682 public static bool TrueForAll <T> (T [] array, Predicate <T> match)
1685 throw new ArgumentNullException ("array");
1687 throw new ArgumentNullException ("match");
1689 foreach (T t in array)
1696 public static void ForEach<T> (T [] array, Action <T> action)
1699 throw new ArgumentNullException ("array");
1701 throw new ArgumentNullException ("action");
1703 foreach (T t in array)
1707 public static TOutput[] ConvertAll<TInput, TOutput> (TInput [] array, Converter<TInput, TOutput> converter)
1710 throw new ArgumentNullException ("array");
1711 if (converter == null)
1712 throw new ArgumentNullException ("converter");
1714 TOutput [] output = new TOutput [array.Length];
1715 for (int i = 0; i < array.Length; i ++)
1716 output [i] = converter (array [i]);
1721 public static int FindLastIndex<T> (T [] array, Predicate <T> match)
1724 throw new ArgumentNullException ("array");
1726 return FindLastIndex<T> (array, 0, array.Length, match);
1729 public static int FindLastIndex<T> (T [] array, int startIndex, Predicate<T> match)
1732 throw new ArgumentNullException ();
1734 return FindLastIndex<T> (array, startIndex, array.Length - startIndex, match);
1737 public static int FindLastIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1740 throw new ArgumentNullException ("array");
1742 throw new ArgumentNullException ("match");
1744 if (startIndex > array.Length || startIndex + count > array.Length)
1745 throw new ArgumentOutOfRangeException ();
1747 for (int i = startIndex + count - 1; i >= startIndex; i--)
1748 if (match (array [i]))
1754 public static int FindIndex<T> (T [] array, Predicate<T> match)
1757 throw new ArgumentNullException ("array");
1759 return FindIndex<T> (array, 0, array.Length, match);
1762 public static int FindIndex<T> (T [] array, int startIndex, Predicate<T> match)
1765 throw new ArgumentNullException ("array");
1767 return FindIndex<T> (array, startIndex, array.Length - startIndex, match);
1770 public static int FindIndex<T> (T [] array, int startIndex, int count, Predicate<T> match)
1773 throw new ArgumentNullException ("array");
1776 throw new ArgumentNullException ("match");
1778 if (startIndex > array.Length || startIndex + count > array.Length)
1779 throw new ArgumentOutOfRangeException ();
1781 for (int i = startIndex; i < startIndex + count; i ++)
1782 if (match (array [i]))
1788 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1789 public static int BinarySearch<T> (T [] array, T value)
1792 throw new ArgumentNullException ("array");
1794 return BinarySearch<T> (array, 0, array.Length, value, null);
1797 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1798 public static int BinarySearch<T> (T [] array, T value, IComparer<T> comparer)
1801 throw new ArgumentNullException ("array");
1803 return BinarySearch<T> (array, 0, array.Length, value, comparer);
1806 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1807 public static int BinarySearch<T> (T [] array, int offset, int length, T value)
1809 return BinarySearch<T> (array, offset, length, value, null);
1812 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1813 public static int BinarySearch<T> (T [] array, int index, int length, T value, IComparer<T> comparer)
1816 throw new ArgumentNullException ("array");
1818 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1819 "index is less than the lower bound of array."));
1821 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
1822 "Value has to be >= 0."));
1823 // re-ordered to avoid possible integer overflow
1824 if (index > array.Length - length)
1825 throw new ArgumentException (Locale.GetText (
1826 "index and length do not specify a valid range in array."));
1827 if (comparer == null)
1828 comparer = Comparer <T>.Default;
1831 int iMax = index + length - 1;
1834 while (iMin <= iMax) {
1835 int iMid = (iMin + iMax) / 2;
1836 iCmp = comparer.Compare (value, array [iMid]);
1843 iMin = iMid + 1; // compensate for the rounding down
1845 } catch (Exception e) {
1846 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1852 public static int IndexOf<T> (T [] array, T value)
1855 throw new ArgumentNullException ("array");
1857 return IndexOf<T> (array, value, 0, array.Length);
1860 public static int IndexOf<T> (T [] array, T value, int startIndex)
1863 throw new ArgumentNullException ("array");
1865 return IndexOf<T> (array, value, startIndex, array.Length - startIndex);
1868 public static int IndexOf<T> (T [] array, T value, int startIndex, int count)
1871 throw new ArgumentNullException ("array");
1873 // re-ordered to avoid possible integer overflow
1874 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1875 throw new ArgumentOutOfRangeException ();
1877 int max = startIndex + count;
1878 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
1879 for (int i = startIndex; i < max; i++) {
1880 if (equalityComparer.Equals (value, array [i]))
1887 public static int LastIndexOf<T> (T [] array, T value)
1890 throw new ArgumentNullException ("array");
1892 return LastIndexOf<T> (array, value, array.Length - 1);
1895 public static int LastIndexOf<T> (T [] array, T value, int startIndex)
1898 throw new ArgumentNullException ("array");
1900 return LastIndexOf<T> (array, value, startIndex, startIndex + 1);
1903 public static int LastIndexOf<T> (T [] array, T value, int startIndex, int count)
1906 throw new ArgumentNullException ("array");
1908 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1909 throw new ArgumentOutOfRangeException ();
1911 EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
1912 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1913 if (equalityComparer.Equals (value, array [i]))
1920 public static T [] FindAll<T> (T [] array, Predicate <T> match)
1923 throw new ArgumentNullException ("array");
1926 throw new ArgumentNullException ("match");
1929 T [] d = new T [array.Length];
1930 foreach (T t in array)
1934 Resize <T> (ref d, pos);
1938 public static bool Exists<T> (T [] array, Predicate <T> match)
1941 throw new ArgumentNullException ("array");
1944 throw new ArgumentNullException ("match");
1946 foreach (T t in array)
1952 public static ReadOnlyCollection<T> AsReadOnly<T> (T[] array)
1955 throw new ArgumentNullException ("array");
1956 return new ReadOnlyCollection<T> (new ArrayReadOnlyList<T> (array));
1959 public static T Find<T> (T [] array, Predicate<T> match)
1962 throw new ArgumentNullException ("array");
1965 throw new ArgumentNullException ("match");
1967 foreach (T t in array)
1974 public static T FindLast<T> (T [] array, Predicate <T> match)
1977 throw new ArgumentNullException ("array");
1980 throw new ArgumentNullException ("match");
1982 for (int i = array.Length - 1; i >= 0; i--)
1983 if (match (array [i]))
1989 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
1991 // The constrained copy should guarantee that if there is an exception thrown
1992 // during the copy, the destination array remains unchanged.
1993 // This is related to System.Runtime.Reliability.CER
1994 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1996 Copy (s, s_i, d, d_i, c);
2002 // This is used internally by the runtime to represent arrays; see #74953.
2004 // Note that you normally can't derive a class from System.Array (CS0644),
2005 // but GMCS makes an exception here for all classes which are nested inside
2008 internal class InternalArray<T> : Array, IList<T>
2010 new public IEnumerator<T> GetEnumerator ()
2012 return new InternalEnumerator (this);
2021 bool ICollection<T>.IsReadOnly {
2027 void ICollection<T>.Clear ()
2029 throw new NotSupportedException ("Collection is read-only");
2032 void ICollection<T>.Add (T item)
2034 throw new NotSupportedException ("Collection is read-only");
2037 bool ICollection<T>.Remove (T item)
2039 throw new NotSupportedException ("Collection is read-only");
2042 public bool Contains (T item)
2045 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2047 int length = this.Length;
2048 for (int i = 0; i < length; i++) {
2050 GetGenericValueImpl (i, out value);
2051 if (item.Equals (value))
2058 public void CopyTo (T[] array, int index)
2061 throw new ArgumentNullException ("array");
2063 // The order of these exception checks may look strange,
2064 // but that's how the microsoft runtime does it.
2066 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2067 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
2068 throw new ArgumentException ();
2070 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2072 throw new ArgumentOutOfRangeException (
2073 "index", Locale.GetText ("Value has to be >= 0."));
2075 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
2078 new public T this [int index] {
2080 if (unchecked ((uint) index) >= unchecked ((uint) Length))
2081 throw new ArgumentOutOfRangeException ("index");
2084 GetGenericValueImpl (index, out value);
2089 throw new NotSupportedException ("Collection is read-only");
2093 void IList<T>.Insert (int index, T item)
2095 throw new NotSupportedException ("Collection is read-only");
2098 void IList<T>.RemoveAt (int index)
2100 throw new NotSupportedException ("Collection is read-only");
2103 public int IndexOf (T item)
2106 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
2108 int length = this.Length;
2109 for (int i = 0; i < length; i++) {
2111 GetGenericValueImpl (i, out value);
2112 if (item.Equals (value))
2113 // array index may not be zero-based.
2115 return i + this.GetLowerBound (0);
2120 // lower bound may be MinValue
2121 retVal = this.GetLowerBound (0) - 1;
2127 // CAUTION! No bounds checking!
2128 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2129 protected extern void GetGenericValueImpl (int pos, out T value);
2131 internal struct InternalEnumerator : IEnumerator<T>
2133 const int NOT_STARTED = -2;
2135 // this MUST be -1, because we depend on it in move next.
2136 // we just decr the size, so, 0 - 1 == FINISHED
2137 const int FINISHED = -1;
2139 InternalArray<T> array;
2142 internal InternalEnumerator (InternalArray<T> array)
2148 public void Dispose ()
2153 public bool MoveNext ()
2155 if (idx == NOT_STARTED)
2158 return idx != FINISHED && -- idx != FINISHED;
2164 throw new InvalidOperationException ();
2166 return array [array.Length - 1 - idx];
2170 void IEnumerator.Reset ()
2172 throw new NotImplementedException ();
2175 object IEnumerator.Current {
2183 class ArrayReadOnlyList<T> : IList<T>
2188 public ArrayReadOnlyList (T [] array)
2191 is_value_type = typeof (T).IsValueType;
2194 public T this [int index] {
2196 if (unchecked ((uint) index) >= unchecked ((uint) array.Length))
2197 throw new ArgumentOutOfRangeException ("index");
2198 return array [index];
2200 set { throw ReadOnlyError (); }
2204 get { return array.Length; }
2207 public bool IsReadOnly {
2208 get { return true; }
2211 public void Add (T item)
2213 throw ReadOnlyError ();
2216 public void Clear ()
2218 throw ReadOnlyError ();
2221 public bool Contains (T item)
2223 return Array.IndexOf<T> (array, item) >= 0;
2226 public void CopyTo (T [] array, int index)
2228 array.CopyTo (array, index);
2231 IEnumerator IEnumerable.GetEnumerator ()
2233 return GetEnumerator ();
2236 public IEnumerator<T> GetEnumerator ()
2238 for (int i = 0; i < array.Length; i++)
2239 yield return array [i];
2242 public int IndexOf (T item)
2244 return Array.IndexOf<T> (array, item);
2247 public void Insert (int index, T item)
2249 throw ReadOnlyError ();
2252 public bool Remove (T item)
2254 throw ReadOnlyError ();
2257 public void RemoveAt (int index)
2259 throw ReadOnlyError ();
2262 Exception ReadOnlyError ()
2264 return new NotSupportedException ("This collection is read-only.");
2270 #if BOOTSTRAP_WITH_OLDLIB
2271 /* delegate used to swap array elements, keep defined outside Array */
2272 delegate void Swapper (int i, int j);