Wed Sep 11 15:26:34 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System / Array.cs
index 044edb1c0df27c341098b88b9d9bca0d403e0a15..43e8344bcdcce50d4422743c841ffb7e4205f356 100644 (file)
-//
+
 // System.Array.cs
 //
-// Author:
+// Authors:
 //   Joe Shaw (joe@ximian.com)
+//   Martin Baulig (martin@gnome.org)
+//   Dietmar Maurer (dietmar@ximian.com)
 //
 // (C) 2001 Ximian, Inc.  http://www.ximian.com
 //
 
-namespace System\r
+using System.Collections;
+using System.Runtime.CompilerServices;
+
+namespace System
 {
 
-       public abstract class Array : ICloneable \r
+       [Serializable]
+       public abstract class Array : ICloneable, ICollection, IList, IEnumerable
        {
-               public int lower_bound = 0;
-               private int length;
-               private int rank;
-
+               // Constructor          
+               private Array ()
+               {
+                       /* empty */
+               }
+               
                // Properties
-               public int Length \r
+               public int Length 
                {
-                       get \r
+                       get 
                        {
+                               int length = this.GetLength (0);
+
+                               for (int i = 1; i < this.Rank; i++) {
+                                       length *= this.GetLength (i); 
+                               }
+                               
                                return length;
                        }
                }
 
-               public int Rank \r
+               public int Rank 
                {
-                       get \r
+                       get
                        {
-                               return rank;
+                               return this.GetRank ();
                        }
                }
 
-               // Methods
-               public static int BinarySearch (Array array, object value)
-               {
-                       return BinarySearch (array, this.lower_bound, this.length, value, null);
+               // IList interface
+               object IList.this [int index] {
+                       get {
+                               return GetValueImpl (index);
+                       } 
+                       set {
+                               SetValueImpl (value, index);
+                       }
                }
 
-               public static int BinarySearch (Array array, object value, IComparer comparer)
+               int IList.Add (object value) {
+                       throw new NotSupportedException ();
+               }
+
+               void IList.Clear () {
+                       Array.Clear (this, this.GetLowerBound(0), this.Length);
+               }
+
+               bool IList.Contains (object value) {
+                       if (this.Rank > 1)
+                               throw new RankException ("Only single dimension arrays are supported.");
+
+                       int length = this.Length;
+                       for (int i = 0; i < length; i++) {
+                               if (value.Equals (this.GetValueImpl (i)))
+                                       return true;
+                       }
+                       return false;
+               }
+
+               int IList.IndexOf (object value) {
+                       if (this.Rank > 1)
+                               throw new RankException ();
+
+                       int length = this.Length;
+                       for (int i = 0; i < length; i++) {
+                               if (value.Equals (this.GetValueImpl (i)))
+                                       // array index may not be zero-based.
+                                       // use lower bound
+                                       return i + this.GetLowerBound (0);
+                       }
+
+                       int retVal;
+                       unchecked {
+                               // lower bound may be MinValue
+                               retVal = this.GetLowerBound (0) - 1;
+                       }
+
+                       return retVal;
+               }
+
+               void IList.Insert (int index, object value) {
+                       throw new NotSupportedException ();
+               }
+
+               void IList.Remove (object value) {
+                       throw new NotSupportedException ();
+               }
+
+               void IList.RemoveAt (int index) {
+                       throw new NotSupportedException ();
+               }
+
+               // InternalCall Methods
+               
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern int GetRank ();
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern int GetLength (int dimension);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern int GetLowerBound (int dimension);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern object GetValue (int[] idxs);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern void SetValue (object value, int[] idxs);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern object GetValueImpl (int pos);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern void SetValueImpl (object value, int pos);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern static void FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);\r
+\r
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]\r
+               internal extern static Array CreateInstanceImpl(Type elementType, int[] lengths, int [] bounds);
+
+               // Properties
+               int ICollection.Count {
+                       get {
+                               return Length;
+                       }
+               }
+
+               [MonoTODO]
+               public virtual bool IsSynchronized {
+                       get {
+                               // FIXME?
+                               return false;
+                       }
+               }
+
+               [MonoTODO]
+               public virtual object SyncRoot {
+                       get {
+                               // FIXME
+                               return null;
+                       }
+               }
+
+               public virtual bool IsFixedSize 
                {
-                       return BinarySearch (array, this.lower_bound, this.length, value, comparer);
+                       get {
+                               return true;
+                       }
                }
 
-               public static int BinarySearch (Array array, int index, int length, object value)
+               public virtual bool IsReadOnly 
                {
-                       return BinarySearch (array, index, length, value, null);
+                       get{
+                               return false;
+                       }
                }
 
-               public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
+               public virtual IEnumerator GetEnumerator ()
                {
-                       if (array == null)
-                               throw new ArgumentNullException ();
+                       return new SimpleEnumerator(this);
+               }
 
-                       if (array.Rank > 1)
-                               throw new RankException ();
+               public int GetUpperBound (int dimension)
+               {
+                       return GetLowerBound (dimension) +
+                               GetLength (dimension) - 1;
+               }
 
-                       if (index < array.lower_bound || length < 0)
-                               throw new ArgumentOutOfRangeException ();
+               public object GetValue (int idx)
+               {
+                       int[] ind = new int [1];
 
-                       if (index + length > array.lower_bound + array.Length)
-                               throw new ArgumentException ();
+                       ind [0] = idx;
 
-                       if (comparer == null && !(value is IComparable))
-                               throw new ArgumentException ();
+                       return GetValue (ind);
+               }
 
-                       // FIXME: Throw an ArgumentException if comparer
-                       // is null and value is not of the same type as the
-                       // elements of array.
+               public object GetValue (int idx1, int idx2)
+               {
+                       int[] ind = new int [2];
 
-                       for (int i = 0; i < length; i++) \r
-                       {
-                               int result;
+                       ind [0] = idx1;
+                       ind [1] = idx2;
 
-                               if (comparer == null && !(array.GetValue(index + i) is IComparable))
-                                       throw new ArgumentException ();
+                       return GetValue (ind);
+               }
 
-                               if (comparer == null)
-                                       result = value.CompareTo(array.GetValue(index + i));
-                               else
-                                       result = comparer.Compare(value, array.GetValue(index + i));
+               public object GetValue (int idx1, int idx2, int idx3)
+               {
+                       int[] ind = new int [3];
 
-                               if (result == 0)
-                                       return index + i;
-                               else if (result < 0)
-                                       return ~(index + i);
-                       }
+                       ind [0] = idx1;
+                       ind [1] = idx2;
+                       ind [2] = idx3;
 
-                       return ~(index + length);
+                       return GetValue (ind);
                }
 
-               public static void Clear (Array array, int index, int length)
+               // This function is currently unused, but just in case we need it later on ... */
+               internal int IndexToPos (int[] idxs)
                {
-                       if (array == null)
+                       if (idxs == null)
                                throw new ArgumentNullException ();
 
-                       if (index < this.lower_bound || length < 0 ||
-                               index + length > this.lower_bound + this.length)
-                               throw new ArgumentOutOfRangeException ();
+                       if ((idxs.Rank != 1) || (idxs.Length != Rank))
+                               throw new ArgumentException ();
 
-                       for (int i = 0; i < length; i++) \r
-                       {
-                               if (array.GetValue(index + i) is bool)
-                                       array.SetValue(false, index + i);
-                               else if (array.GetValue(index + i) is ValueType)
-                                       array.SetValue(0, index + i);
-                               else
-                                       array.SetValue(null, index + i);
+                       if ((idxs [0] < GetLowerBound (0)) || (idxs [0] > GetUpperBound (0)))
+                               throw new IndexOutOfRangeException();
+
+                       int pos = idxs [0] - GetLowerBound (0);
+                       for (int i = 1; i < Rank; i++) {
+                               if ((idxs [i] < GetLowerBound (i)) || (idxs [i] > GetUpperBound (i)))
+                                       throw new IndexOutOfRangeException();
+
+                               pos *= GetLength (i);
+                               pos += idxs [i] - GetLowerBound (i);
                        }
+
+                       return pos;
                }
 
-               public virtual object Clone ()
+               public void SetValue (object value, int idx)
                {
-                       Array a = new Array();
+                       int[] ind = new int [1];
 
-                       for (int i = 0; i < this.length; i++) \r
-                       {
-                               int index = this.lower_bound + i;
+                       ind [0] = idx;
 
-                               a.SetValue(this.GetValue(index), index);
-                       }
+                       SetValue (value, ind);
+               }
+               
+               public void SetValue (object value, int idx1, int idx2)
+               {
+                       int[] ind = new int [2];
 
-                       return a;
+                       ind [0] = idx1;
+                       ind [1] = idx2;
+
+                       SetValue (value, ind);
                }
 
-               public static void Copy (Array source, Array dest, int length)
+               public void SetValue (object value, int idx1, int idx2, int idx3)
                {
-                       Copy (source, source.lower_bound, dest, dest.lower_bound, length);
+                       int[] ind = new int [3];
+
+                       ind [0] = idx1;
+                       ind [1] = idx2;
+                       ind [2] = idx3;
+
+                       SetValue (value, ind);
                }
 
-               public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
+               public static Array CreateInstance(Type elementType, int length)
+               {
+                       int[] lengths = new int [1];
+                       int[] bounds = null;
+                       
+                       lengths [0] = length;
+                       
+                       return CreateInstanceImpl (elementType, lengths, bounds);
+               }
+               
+               public static Array CreateInstance(Type elementType, int l1, int l2)
+               {
+                       int[] lengths = new int [2];
+                       int[] bounds = null;
+                       
+                       lengths [0] = l1;
+                       lengths [1] = l2;
+                       
+                       return CreateInstanceImpl (elementType, lengths, bounds);
+               }
+
+               public static Array CreateInstance(Type elementType, int l1, int l2, int l3)
                {
+                       int[] lengths = new int [3];
+                       int[] bounds = null;
+                       
+                       lengths [0] = l1;
+                       lengths [1] = l2;
+                       lengths [2] = l3;
+               
+                       return CreateInstanceImpl (elementType, lengths, bounds);
+               }
+
+               public static Array CreateInstance(Type elementType, int[] lengths)
+               {
+                       int[] bounds = null;
+                       
+                       return CreateInstanceImpl (elementType, lengths, bounds);
+               }
+
+               public static Array CreateInstance(Type elementType, int[] lengths, int [] bounds)
+               {
+                       if (bounds == null)
+                               throw new ArgumentNullException("bounds");
+
+                       return CreateInstanceImpl (elementType, lengths, bounds);
+               }
+
+               
+               public static int BinarySearch (Array array, object value)
+               {
+                       if (array == null)
+                               throw new ArgumentNullException("array");
+
+                       if (array.Rank > 1)
+                               throw new RankException();
+
+                       if (!(value is IComparable))
+                               throw new ArgumentException("value does not support IComparable");
+
+                       return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
+                                            value, null);
+               }
+
+               public static int BinarySearch (Array array, object value, IComparer comparer)
+               {
+                       if (array == null)
+                               throw new ArgumentNullException("array");
+
+                       if (array.Rank > 1)
+                               throw new RankException();
+
+                       if ((comparer == null) && !(value is IComparable))
+                               throw new ArgumentException("comparer is null and value does not support IComparable");
+
+                       return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
+                                            value, comparer);
+               }
+
+               public static int BinarySearch (Array array, int index, int length, object value)
+               {
+                       if (array == null)
+                               throw new ArgumentNullException("array");
+
+                       if (array.Rank > 1)
+                               throw new RankException();
+
+                       if (index < array.GetLowerBound (0))
+                               throw new ArgumentOutOfRangeException("index is less than the lower bound of array.");
                        if (length < 0)
-                               throw new ArgumentOutOfRangeException ();
+                               throw new ArgumentOutOfRangeException("length is less than zero.");
 
-                       if (source == null || dest == null)
-                               throw new ArgumentNullException ();
+                       if (index + length > array.GetLowerBound (0) + array.GetLength (0))
+                               throw new ArgumentException("index and length do not specify a valid range in array.");
+                       if (!(value is IComparable))
+                               throw new ArgumentException("value does not support IComparable");
 
-                       if (source_idx < source.lower_bound || source_idx + length > source.lower_bound + source.Length || dest_idx < dest.lower_bound || dest_idx + length > dest.lower_bound + dest.Length)
-                               throw new ArgumentException ();
+                       return BinarySearch (array, index, length, value, null);
+               }
 
-                       if (source.Rank != dest.Rank)
+               public static int BinarySearch (Array array, int index,
+                                               int length, object value,
+                                               IComparer comparer)
+               {
+                       if (array == null)
+                               throw new ArgumentNullException ("array");
+
+                       if (array.Rank > 1)
                                throw new RankException ();
 
-                       for (int i = 0; i < length; i++) \r
-                       {
-                               int index = source.lower_bound + i;
+                       if (index < array.GetLowerBound (0))
+                               throw new ArgumentOutOfRangeException("index is less than the lower bound of array.");
+                       if (length < 0)
+                               throw new ArgumentOutOfRangeException("length is less than zero.");
 
-                               dest.SetValue(source.GetValue(index), index);
+                       if (index + length > array.GetLowerBound (0) + array.GetLength (0))
+                               throw new ArgumentException("index and length do not specify a valid range in array.");
+
+                       if ((comparer == null) && !(value is IComparable))
+                               throw new ArgumentException("comparer is null and value does not support IComparable");
+
+                       // cache this in case we need it
+                       IComparable valueCompare = value as IComparable;
+
+                       int iMin = index;
+                       int iMax = index + length;
+                       int iCmp = 0;
+                       try
+                       {
+                               // there's a subtle balance here between
+                               // 1) the while condition
+                               // 2) the rounding down of the '/ 2'
+                               // 3) the asymetrical recursion
+                               // 4) the fact that iMax starts beyond the end of the array
+                               while (iMin < iMax)
+                               {
+                                       int iMid = (iMin + iMax) / 2;
+                                       object elt = array.GetValueImpl (iMid);
+
+                                       // this order is from MSDN
+                                       if (comparer != null)
+                                               iCmp = comparer.Compare (value, elt);
+                                       else
+                                       {
+                                               IComparable eltCompare = elt as IComparable;
+                                               if (eltCompare != null)
+                                                       iCmp = -eltCompare.CompareTo (value);
+                                               else
+                                                       iCmp = valueCompare.CompareTo (elt);
+                                       }
+
+                                       if (iCmp == 0)
+                                               return iMid;
+                                       else if (iCmp < 0)
+                                               iMax = iMid;
+                                       else
+                                               iMin = iMid + 1;        // compensate for the rounding down
+                               }
+                       }
+                       catch (InvalidCastException e)
+                       {
+                               throw new ArgumentException ("array", e);
                        }
-               }
 
-               [MethodImplAttribute(InternalCall)]
-               private object InternalGetValue (int index);
+                       if (iCmp > 0)
+                               return ~iMax;
+                       else
+                               return ~iMin;
+               }
 
-               public object GetValue (int index)
+               public static void Clear (Array array, int index, int length)
                {
-                       if (this.rank > 1)
-                               throw new ArgumentException ();
+                       if (array == null)
+                               throw new ArgumentNullException ();
+
+                       if (array.Rank > 1)
+                               throw new RankException ();
 
-                       if (index < this.lower_bound ||
-                               index > this.lower_bound + this.length)
+                       if (index < array.GetLowerBound (0) || length < 0 ||
+                               index + length > array.GetUpperBound (0) + 1)
                                throw new ArgumentOutOfRangeException ();
-                       
-                       return InternalGetValue (index);
+
+                       for (int i = 0; i < length; i++) 
+                       {
+                               array.SetValueImpl(null, index + i);
+                       }
                }
 
-               [MethodImplAttribute(InternalCall)]
-               private void InternalSetValue (object value, int index);
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public virtual extern object Clone ();
 
-               public void SetValue (object value, int index)
+               public static void Copy (Array source, Array dest, int length)
                {
-                       if (this.rank > 1)
-                               throw new ArgumentException ();
+                       // need these checks here because we are going to use
+                       // GetLowerBound() on source and dest.
+                       if (source == null)
+                               throw new ArgumentNullException ("null");
 
-                       if (index < this.lower_bound ||
-                               index > this.lower_bound + this.length)
-                               throw new ArgumentOutOfRangeException ();
+                       if (dest == null)
+                               throw new ArgumentNullException ("dest");
 
-                       InternalSetValue (value);
+                       Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);                  
                }
 
+               public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("null");
+
+                       if (dest == null)
+                               throw new ArgumentNullException ("dest");
+
+                       if (length < 0)
+                               throw new ArgumentOutOfRangeException ("length");
+
+                       if (source_idx < 0)
+                               throw new ArgumentException ("source_idx");
+
+                       if (dest_idx < 0)
+                               throw new ArgumentException ("dest_idx");
+
+                       int source_pos = source_idx - source.GetLowerBound (0);
+                       int dest_pos = dest_idx - dest.GetLowerBound (0);
+
+
+                       if (source_pos + length > source.Length || dest_pos + length > dest.Length)
+                               throw new ArgumentException ("length");
+
+                       if (source.Rank != dest.Rank)
+                               throw new RankException ();
+
+                       Type src_type = source.GetType ().GetElementType ();
+                       Type dst_type = dest.GetType ().GetElementType ();
+
+                       if (src_type == dst_type) {
+                               FastCopy (source, source_pos, dest, dest_pos, length);
+                               return;
+                       }
+
+                       if (!Object.ReferenceEquals (source, dest) || source_pos > dest_pos)
+                       {
+                               for (int i = 0; i < length; i++) 
+                               {
+                                       Object srcval = source.GetValueImpl (source_pos + i);
+
+                                       try {
+                                               dest.SetValueImpl (srcval, dest_pos + i);
+                                       } catch {
+                                               if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
+                                                       (src_type.Equals (typeof (Object))))
+                                                       throw new InvalidCastException ();
+                                               else
+                                                       throw new ArrayTypeMismatchException (
+                                                               String.Format ("(Types: source={0};  target={1})", src_type.FullName, dst_type.FullName));
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               for (int i = length - 1; i >= 0; i--) 
+                               {
+                                       Object srcval = source.GetValueImpl (source_pos + i);
+
+                                       try {
+                                               dest.SetValueImpl (srcval, dest_pos + i);
+                                       } catch {
+                                               if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
+                                                       (src_type.Equals (typeof (Object))))
+                                                       throw new InvalidCastException ();
+                                               else
+                                                       throw new ArrayTypeMismatchException (
+                                                               String.Format ("(Types: source={0};  target={1})", src_type.FullName, dst_type.FullName));
+                                       }
+                               }
+                       }
+               }
+               
                public static int IndexOf (Array array, object value)
                {
+                       if (array == null)
+                               throw new ArgumentNullException ();
+       
                        return IndexOf (array, value, 0, array.Length);
                }
 
                public static int IndexOf (Array array, object value, int index)
                {
+                       if (array == null)
+                               throw new ArgumentNullException ();
+
                        return IndexOf (array, value, index, array.Length - index);
                }
-
+               
                public static int IndexOf (Array array, object value, int index, int length)
                {
                        if (array == null)
                                throw new ArgumentNullException ();
        
-                       if (length < 0 || index < array.lower_bound || index > array.lower_bound + length)
+                       if (array.Rank > 1)
+                               throw new RankException ();
+
+                       if (length < 0 || index < array.GetLowerBound (0) ||
+                           index+length-1 > array.GetUpperBound (0))
                                throw new ArgumentOutOfRangeException ();
 
-                       for (int i = 0; i < length; i++) \r
+                       for (int i = 0; i < length; i++)
                        {
-                               if (array.GetValue(index + i) == value)
+                               if (array.GetValueImpl(index + i).Equals(value))
                                        return index + i;
                        }
 
-                       return array.lower_bound - 1;
+                       return array.GetLowerBound (0) - 1;
                }
 
                public static int LastIndexOf (Array array, object value)
                {
-                       return LastIndexOf (array, value, 0, array.Length);
+                       if (array == null)
+                               throw new ArgumentNullException ();
+       
+                       return LastIndexOf (array, value, array.Length-1);
                }
 
                public static int LastIndexOf (Array array, object value, int index)
                {
-                       return LastIndexOf (array, value, index, array.Length - index);
+                       if (array == null)
+                               throw new ArgumentNullException ();
+       
+                       return LastIndexOf (array, value, index, index-array.GetLowerBound(0)+1);
                }
-
+               
                public static int LastIndexOf (Array array, object value, int index, int length)
                {
                        if (array == null)
                                throw new ArgumentNullException ();
        
-                       if (length < 0 || index < array.lower_bound || index > array.lower_bound + length)
+                       if (array.Rank > 1)
+                               throw new RankException ();
+
+                       if (length < 0 || index-length+1 < array.GetLowerBound (0) ||
+                           index > array.GetUpperBound (0))
                                throw new ArgumentOutOfRangeException ();
 
-                       for (int i = length - 1; i >= 0; i--) \r
+                       for (int i = index; i >= index-length+1; i--)
                        {
-                               if (array.GetValue(index + i) == value)
-                                       return index + i;
+                               if (array.GetValueImpl(i).Equals(value))
+                                       return i;
                        }
 
-                       return array.lower_bound - 1;
+                       return array.GetLowerBound (0) - 1;
                }
-       
+
                public static void Reverse (Array array)
                {
-                       Reverse (array, array.lower_bound, array.Length);
+                       if (array == null)
+                               throw new ArgumentNullException ();
+
+                       Reverse (array, array.GetLowerBound (0), array.GetLength (0));
                }
 
                public static void Reverse (Array array, int index, int length)
@@ -249,35 +638,44 @@ namespace System
                        if (array.Rank > 1)
                                throw new RankException ();
 
-                       if (index < array.lower_bound || length < 0)
+                       if (index < array.GetLowerBound (0) || length < 0)
                                throw new ArgumentOutOfRangeException ();
 
-                       if (index + length > array.lower_bound + array.Length)
+                       if (index + length > array.GetUpperBound (0) + 1)
                                throw new ArgumentException ();
 
-                       for (int i = 0; i < length/2; i++) \r
+                       for (int i = 0; i < length/2; i++)
                        {
                                object tmp;
 
-                               tmp = array.GetValue(index + i);
-                               array.SetValue(array.GetValue(index + length - i - 1), index + i);
-                               array.SetValue(tmp, index + length - i - 1);
+                               tmp = array.GetValueImpl (index + i);
+                               array.SetValueImpl(array.GetValueImpl (index + length - i - 1), index + i);
+                               array.SetValueImpl(tmp, index + length - i - 1);
                        }
-               }
-
+               }               
+               
                public static void Sort (Array array)
                {
-                       Sort (array, null, array.lower_bound, array.Length, null);
+                       if (array == null)
+                               throw new ArgumentNullException ();
+
+                       Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
                }
 
                public static void Sort (Array keys, Array items)
                {
-                       Sort (keys, items, keys.lower_bound, keys.Length, null);
+                       if (keys == null)
+                               throw new ArgumentNullException ();
+
+                       Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
                }
 
                public static void Sort (Array array, IComparer comparer)
                {
-                       Sort (array, null, array.lower_bound, array.Length, comparer);
+                       if (array == null)
+                               throw new ArgumentNullException ();
+
+                       Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
                }
 
                public static void Sort (Array array, int index, int length)
@@ -287,7 +685,10 @@ namespace System
 
                public static void Sort (Array keys, Array items, IComparer comparer)
                {
-                       Sort (keys, items, keys.lower_bound, keys.Length, comparer);
+                       if (keys == null)
+                               throw new ArgumentNullException ();
+
+                       Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
                }
 
                public static void Sort (Array keys, Array items, int index, int length)
@@ -310,54 +711,55 @@ namespace System
 
                private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
                {
-                       int pivot;
-                       int low = low0;
-                       int high = high0;
+                       if (keys == null)
+                               throw new ArgumentNullException ();
 
-                       if (low >= high)
-                               return;
+                       if (keys.Rank > 1 || (items != null && items.Rank > 1))
+                               throw new RankException ();
 
-                       pivot = (low + high) / 2;
+                       if (low0 >= high0)
+                               return;
 
-                       if (compare(keys.GetValue(low), keys.GetValue(pivot), comparer) > 0)
-                               swap(keys, items, low, pivot);
+                       int low = low0;
+                       int high = high0;
 
-                       if (compare(keys.GetValue(pivot), keys.GetValue(high), comparer) > 0)
-                               swap(keys, items, pivot, high);
+                       object objPivot = keys.GetValueImpl ((low + high) / 2);
 
-                       while (low < high) \r
+                       while (low <= high)
                        {
                                // Move the walls in
-                               while (low < high && compare(keys.GetValue(low), keys.GetValue(pivot), comparer) < 0)
-                                       low++;
-                               while (low < high && compare(keys.GetValue(pivot), keys.GetValue(high), comparer) < 0)
-                                       high--;
+                               while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
+                                       ++low;
+                               while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
+                                       --high;
 
-                               if (low < high) \r
+                               if (low <= high)
                                {
-                                       swap(keys, items, low, high);
-                                       low++;
-                                       high--;
+                                       swap (keys, items, low, high);
+                                       ++low;
+                                       --high;
                                }
                        }
 
-                       qsort (keys, items, low0, low - 1);
-                       qsort (keys, items, high + 1, high0);
+                       if (low0 < high)
+                               qsort (keys, items, low0, high, comparer);
+                       if (low < high0)
+                               qsort (keys, items, low, high0, comparer);
                }
 
                private static void swap (Array keys, Array items, int i, int j)
                {
                        object tmp;
 
-                       tmp = keys.GetValue(i);
-                       keys.SetValue(keys.GetValue(j), i);
-                       keys.SetValue(tmp, j);
+                       tmp = keys.GetValueImpl (i);
+                       keys.SetValueImpl (keys.GetValue (j), i);
+                       keys.SetValueImpl (tmp, j);
 
-                       if (items != null) \r
+                       if (items != null)
                        {
-                               tmp = items.GetValue(i);
-                               items.SetValue(items.GetValue(j), i);
-                               items.SetValue(tmp, j);
+                               tmp = items.GetValueImpl (i);
+                               items.SetValueImpl (items.GetValueImpl (j), i);
+                               items.SetValueImpl (tmp, j);
                        }
                }
 
@@ -368,5 +770,69 @@ namespace System
                        else
                                return comparer.Compare(value1, value2);
                }
+       
+               public virtual void CopyTo (Array array, int index)
+               {
+                       if (array == null)
+                               throw new ArgumentNullException ();
+
+                       // The order of these exception checks may look strange,
+                       // but that's how the microsoft runtime does it.
+                       if (this.Rank > 1)
+                               throw new RankException ();
+                       if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
+                               throw new ArgumentException ();
+                       if (array.Rank > 1)
+                               throw new RankException ();
+                       if (index < 0)
+                               throw new ArgumentOutOfRangeException ();
+
+                       Copy (this, this.GetLowerBound(0), array, index, this.GetLength (0));
+               }
+
+               internal class SimpleEnumerator : IEnumerator {
+                       Array enumeratee;
+                       int currentpos;
+                       int length;
+
+                       public SimpleEnumerator (Array arrayToEnumerate) {
+                               this.enumeratee = arrayToEnumerate;
+                               this.currentpos = -1;
+                               this.length = arrayToEnumerate.Length;
+                       }
+
+                       public object Current {
+                               get {
+                                       // Exception messages based on MS implementation
+                                       if (currentpos < 0 ) {
+                                               throw new InvalidOperationException
+                                                       ("Enumeration has not started");
+                                       }
+                                       if  (currentpos >= length) {
+                                               throw new InvalidOperationException
+                                                       ("Enumeration has already ended");
+                                       }
+                                       // Current should not increase the position. So no ++ over here.
+                                       return enumeratee.GetValueImpl(currentpos);
+                               }
+                       }
+
+                       public bool MoveNext() {
+                               //The docs say Current should throw an exception if last
+                               //call to MoveNext returned false. This means currentpos
+                               //should be set to length when returning false.
+                                       if (currentpos < length) {
+                                               currentpos++;
+                                       }
+                               if(currentpos < length)
+                                       return true;
+                               else
+                                       return false;
+                       }
+
+                       public void Reset() {
+                               currentpos= -1;
+                       }
+               }
        }
 }