Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / corlib / System.Collections.Generic / List.cs
index 7646b777ba77533e9f093590931c67355afa362c..564e6b674a1910d922b8415e906cb3c5519717b1 100644 (file)
@@ -6,9 +6,11 @@
 //    Martin Baulig (martin@ximian.com)
 //    Carlos Alberto Cortez (calberto.cortez@gmail.com)
 //    David Waite (mass@akuma.org)
+//    Marek Safar (marek.safar@gmail.com)
 //
 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 // Copyright (C) 2005 David Waite
+// Copyright (C) 2011,2012 Xamarin, Inc (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 using System.Collections.ObjectModel;
 using System.Runtime.InteropServices;
 using System.Diagnostics;
+using System.Runtime.CompilerServices;
 
 namespace System.Collections.Generic {
        [Serializable]
        [DebuggerDisplay ("Count={Count}")]
        [DebuggerTypeProxy (typeof (CollectionDebuggerView<>))]
-       public class List <T> : IList <T>, IList, ICollection {
+       public class List<T> : IList<T>, IList
+#if NET_4_5
+               , IReadOnlyList<T>
+#endif
+       {
                T [] _items;
                int _size;
                int _version;
                
-               static readonly T [] EmptyArray = new T [0]; 
                const int DefaultCapacity = 4;
                
                public List ()
                {
-                       _items = EmptyArray;
+                       _items = EmptyArray<T>.Value;
                }
                
                public List (IEnumerable <T> collection)
@@ -59,7 +65,7 @@ namespace System.Collections.Generic {
                        // initialize to needed size (if determinable)
                        ICollection <T> c = collection as ICollection <T>;
                        if (c == null) {
-                               _items = EmptyArray;
+                               _items = EmptyArray<T>.Value;;
                                AddEnumerable (collection);
                        } else {
                                _size = c.Count;
@@ -87,7 +93,7 @@ namespace System.Collections.Generic {
                        // we can speed things up by 25%
                        if (_size == _items.Length)
                                GrowIfNeeded (1);
-                       _items [_size ++] = item;
+                       Array.UnsafeStore (_items, _size++, item);
                        _version++;
                }
                
@@ -467,6 +473,8 @@ namespace System.Collections.Generic {
 
                public int LastIndexOf (T item)
                {
+                       if (_size == 0)
+                               return -1;
                        return Array.LastIndexOf<T> (_items, item, _size - 1, _size);
                }
                
@@ -627,16 +635,19 @@ namespace System.Collections.Generic {
                }
                
                public T this [int index] {
+                       [MethodImpl ((MethodImplOptions)256)]
                        get {
                                if ((uint) index >= (uint) _size)
                                        throw new ArgumentOutOfRangeException ("index");
-                               return _items [index];
+                               return Array.UnsafeLoad (_items, index);
                        }
+
+                       [MethodImpl ((MethodImplOptions)256)]
                        set {
-                               CheckIndex (index);
-                               if ((uint) index == (uint) _size)
+                               if ((uint) index >= (uint) _size)
                                        throw new ArgumentOutOfRangeException ("index");
-                               _items [index] = value;
+                               Array.UnsafeStore (_items, index, value);
+                               _version++;
                        }
                }
                
@@ -755,9 +766,9 @@ namespace System.Collections.Generic {
                                
                [Serializable]
                public struct Enumerator : IEnumerator <T>, IDisposable {
-                       List <T> l;
+                       readonly List<T> l;
                        int next;
-                       int ver;
+                       readonly int ver;
 
                        T current;
 
@@ -770,47 +781,41 @@ namespace System.Collections.Generic {
                        
                        public void Dispose ()
                        {
-                               l = null;
                        }
 
-                       void VerifyState ()
-                       {
-                               if (l == null)
-                                       throw new ObjectDisposedException (GetType ().FullName);
-                               if (ver != l._version)
-                                       throw new InvalidOperationException (
-                                               "Collection was modified; enumeration operation may not execute.");
-                       }
-                       
                        public bool MoveNext ()
                        {
-                               VerifyState ();
-
-                               if (next < 0)
-                                       return false;
+                               var list = l;
 
-                               if (next < l._size) {
-                                       current = l._items [next++];
+                               if ((uint)next < (uint)list._size && ver == list._version) {
+                                       current = list._items [next++];
                                        return true;
                                }
 
+                               if (ver != l._version)
+                                       throw new InvalidOperationException ("Collection was modified; enumeration operation may not execute.");
+
                                next = -1;
                                return false;
                        }
-                       
+
                        public T Current {
                                get { return current; }
                        }
                        
                        void IEnumerator.Reset ()
                        {
-                               VerifyState ();
+                               if (ver != l._version)
+                                       throw new InvalidOperationException ("Collection was modified; enumeration operation may not execute.");
+
                                next = 0;
                        }
                        
                        object IEnumerator.Current {
                                get {
-                                       VerifyState ();
+                                       if (ver != l._version)
+                                               throw new InvalidOperationException ("Collection was modified; enumeration operation may not execute.");
+
                                        if (next <= 0)
                                                throw new InvalidOperationException ();
                                        return current;