List泛型

.Net自从2.0以后开始支持泛型。

泛型的作用:可以创建独立于被包含类型的类和方法。泛型类使用泛型类型,并可以根据需要使用特定的类型替换泛型类型。这就保证了类型安全性:如果某个类型不支持泛型类,编译器就会出现错误。

不多说,先记录一下源码:

   1 // ==++==
   2 // 
   3    Copyright (c) Microsoft Corporation.  All rights reserved.
   4    5  ==--==
   6 /*============================================================
   7 **
   8 ** Class:  List
   9 ** 
  10 ** <OWNER>Microsoft</OWNER>
  11   12 ** Purpose: Implements a generic,dynamically sized list as an 
  13 **          array.
  14   15   16 ===========================================================*/
  17 namespace System.Collections.Generic {
  18 
  19     using System;
  20      System.Runtime;
  21      System.Runtime.Versioning;
  22      System.Diagnostics;
  23      System.Diagnostics.Contracts;
  24      System.Collections.ObjectModel;
  25      System.Security.Permissions;
  26 
  27      Implements a variable-size List that uses an array of objects to store the
  28      elements. A List has a capacity,which is the allocated length
  29      of the internal array. As elements are added to a List,the capacity
  30      of the List is automatically increased as required by reallocating the
  31      internal array.
  32       33     [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
  34     [DebuggerDisplay("Count = {Count}")]
  35     [Serializable]
  36     public class List<T> : IList<T>,System.Collections.IList,IReadOnlyList<T>
  37     {
  38         private const int _defaultCapacity = 4;
  39 
  40         private T[] _items;
  41         [ContractPublicPropertyName(Count  42         int _size;
  43          _version;
  44         [NonSerialized]
  45          Object _syncRoot;
  46         
  47         static readonly T[]  _emptyArray = new T[0];        
  48             
  49          Constructs a List. The list is initially empty and has a capacity
  50          of zero. Upon adding the first element to the list the capacity is
  51          increased to 16,and then increased in multiples of two as required.
  52         public List() {
  53             _items = _emptyArray;
  54         }
  55     
  56          Constructs a List with a given initial capacity. The list is
  57          initially empty,but will have room for the given number of elements
  58          before any reallocations are required.
  59           60         public List( capacity) {
  61             if (capacity < ) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity,ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
  62             Contract.EndContractBlock();
  63 
  64             if (capacity == )
  65                 _items =  66             else
  67                 _items = new T[capacity];
  68   69     
  70          Constructs a List,copying the contents of the given collection. The
  71          size and capacity of the new list will both be equal to the size of the
  72          given collection.
  73           74         public List(IEnumerable<T> collection) {
  75             if (collection==null  76                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
  77   78 
  79             ICollection<T> c = collection as ICollection<T>  80             if( c != ) {
  81                 int count = c.Count;
  82                 if (count ==   83                 {
  84                     _items =  85                 }
  86                 else {
  87                     _items =  T[count];
  88                     c.CopyTo(_items,);
  89                     _size = count;
  90   91             }    
  92              {                
  93                 _size =   94                 _items =  95                  This enumerable could be empty.  Let Add allocate a new array,if needed.
  96                  Note it will also go to _defaultCapacity first,not 1,then 2,etc.
  97                 
  98                 using(IEnumerator<T> en = collection.GetEnumerator()) {
  99                     while(en.MoveNext()) {
 100                         Add(en.Current);                                    
 101                     }
 102  103             }
 104  105         
 106          Gets and sets the capacity of this list.  The capacity is the size of
 107          the internal array used to hold items.  When set,the internal 
 108          array of the list is reallocated to the given capacity.
 109          110          Capacity {
 111             get 112                 Contract.Ensures(Contract.Result<int>() >=  113                 return _items.Length;
 114  115             set 116                 if (value < _size) {
 117                     ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value,ExceptionResource.ArgumentOutOfRange_SmallCapacity);
 118  119                 Contract.EndContractBlock();
 120 
 121                 if (value != _items.Length) {
 122                     if (value >  123                         T[] newItems =  T[value];
 124                         if (_size >  125                             Array.Copy(_items,1)">0,newItems,1)">,_size);
 126                         }
 127                         _items = newItems;
 128  129                      130                         _items = 131  132  133  134  135             
 136          Read-only property describing how many elements are in the List.
 137          Count {
 138              139                 Contract.Ensures(Contract.Result< 140                  _size; 
 141  142  143 
 144         bool System.Collections.IList.IsFixedSize {
 145             get { return false; }
 146  147 
 148             
 149          Is this List read-only?
 150         bool ICollection<T>.IsReadOnly {
 151              152  153 
 154          System.Collections.IList.IsReadOnly {
 155              156  157 
 158          Is this List synchronized (thread-safe)?
 159          System.Collections.ICollection.IsSynchronized {
 160              161  162     
 163          Synchronization root for this object.
 164         Object System.Collections.ICollection.SyncRoot {
 165              { 
 166                 if( _syncRoot ==  167                     System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot,new Object(),1)">);    
 168  169                  _syncRoot;
 170  171  172          Sets or Gets the element at the given index.
 173          174         public T this[ index] {
 175              176                  Following trick can reduce the range check by one
 177                 if ((uint) index >= (uint)_size) {
 178                     ThrowHelper.ThrowArgumentOutOfRangeException();
 179  180  181                  _items[index]; 
 182  183 
 184              185                  186  187  188  189                 _items[index] = value;
 190                 _version++ 191  192  193 
 194         bool IsCompatibleObject(object value) {
 195              Non-null values are fine.  Only accept nulls if T is a class or Nullable<U>.
 196              Note that default(T) is not equal to null for value types except when T is Nullable<U>. 
 197             return ((value is T) || (value == null && default(T) == ));
 198  199 
 200         Object System.Collections.IList. 201              202                 this[index];
 203  204              205                 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value,ExceptionArgument.value);
 206 
 207                 try 208                     this[index] = (T)value;               
 209  210                 catch (InvalidCastException) { 
 211                     ThrowHelper.ThrowWrongValueTypeArgumentException(value,1)">typeof(T));            
 212  213  214  215 
 216          Adds the given object to the end of this list. The size of the list is
 217          increased by one. If required,the capacity of the list is doubled
 218          before adding the new element.
 219         //
 220         void Add(T item) {
 221             if (_size == _items.Length) EnsureCapacity(_size + 1 222             _items[_size++] = item;
 223             _version++ 224  225 
 226          System.Collections.IList.Add(Object item)
 227         {
 228             ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item,ExceptionArgument.item);
 229 
 230              231                 Add((T) item);            
 232  233              234                 ThrowHelper.ThrowWrongValueTypeArgumentException(item,1)"> 235  236 
 237             return Count -  238  239 
 240 
 241          Adds the elements of the given collection to the end of this list. If
 242          required,the capacity of the list is increased to twice the previous
 243          capacity or the new size,whichever is larger.
 244          245         void AddRange(IEnumerable<T> 246             Contract.Ensures(Count >= Contract.OldValue(Count));
 247 
 248             InsertRange(_size,collection);
 249  250 
 251         public ReadOnlyCollection<T> AsReadOnly() {
 252             Contract.Ensures(Contract.Result<ReadOnlyCollection<T>>() !=  253             new ReadOnlyCollection<T>( 254  255            
 256          Searches a section of the list for a given element using a binary search
 257          algorithm. Elements of the list are compared to the search value using
 258          the given IComparer interface. If comparer is null,elements of
 259          the list are compared to the search value using the IComparable
 260          interface,which in that case must be implemented by all elements of the
 261          list and the given search value. This method assumes that the given
 262          section of the list is already sorted; if this is not the case,the
 263          result will be incorrect.
 264         //
 265          The method returns the index of the given value in the list. If the
 266          list does not contain the given value,the method returns a negative
 267          integer. The bitwise complement operator (~) can be applied to a
 268          negative result to produce the index of the first element (if any) that
 269          is larger than the given search value. This is also the index at which
 270          the search value should be inserted into the list in order for the list
 271          to remain sorted.
 272          273          The method uses the Array.BinarySearch method to perform the
 274          search.
 275          276         int BinarySearch(int index,1)">int count,T item,IComparer<T> comparer) {
 277             if (index <  278                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index,1)"> 279             if (count <  280                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count,1)"> 281             if (_size - index < count)
 282                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
 283             Contract.Ensures(Contract.Result<int>() <= index + count);
 284  285 
 286             return Array.BinarySearch<T>(_items,index,count,item,comparer);
 287  288     
 289          BinarySearch(T item)
 290  291             Contract.Ensures(Contract.Result<int>() <= Count);
 292             return BinarySearch( 293  294 
 295         int BinarySearch(T item,1)"> comparer)
 296  297             Contract.Ensures(Contract.Result< 298              299  300 
 301     
 302          Clears the contents of List.
 303          Clear() {
 304              305             {
 306                 Array.Clear(_items,_size);  Don't need to doc this but we clear the elements so that the gc can reclaim the references.
 307                 _size =  308  309             _version++ 310  311     
 312          Contains returns true if the specified element is in the List.
 313          It does a linear,O(n) search.  Equality is determined by calling
 314          item.Equals().
 315          316          Contains(T item) {
 317             if ((Object) item ==  318                 for(int i=0; i<_size; i++ 319                     if ((Object) _items[i] ==  320                         true 321                  322  323              324                 EqualityComparer<T> c = EqualityComparer<T>.Default;
 325                  326                     if (c.Equals(_items[i],item))  327  328                  329  330  331 
 332          System.Collections.IList.Contains(Object item)
 333  334             if(IsCompatibleObject(item)) {            
 335                  Contains((T) item);                
 336  337              338  339 
 340         public List<TOutput> ConvertAll<TOutput>(Converter<T,TOutput> converter) {
 341             if( converter ==  342                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
 343  344              @
 345 
 346 
 347  348 
 349             List<TOutput> list = new List<TOutput>(_size);
 350             for( int i = 0; i< _size; i++ 351                 list._items[i] = converter(_items[i]);
 352  353             list._size = 354              list;
 355  356 
 357          Copies this List into array,which must be of a 
 358          compatible array type.  
 359          360          CopyTo(T[] array) {
 361             CopyTo(array,1)"> 362  363 
 364          365          366          367         void System.Collections.ICollection.CopyTo(Array array,1)"> arrayIndex) {
 368             if ((array != null) && (array.Rank != )) {
 369                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
 370  371  372 
 373              374                  Array.Copy will check for NULL.
 375                 Array.Copy(_items,array,arrayIndex,1)"> 376  377             (ArrayTypeMismatchException){
 378                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
 379  380  381     
 382          Copies a section of this list to the given array at the given index.
 383          384          The method uses the Array.Copy method to copy the elements.
 385          386         void CopyTo(int arrayIndex,1)"> count) {
 387              388  389  390  391             
 392              Delegate rest of error checking to Array.Copy.
 393             Array.Copy(_items,count);
 394  395 
 396         void CopyTo(T[] array,1)"> 397              398             Array.Copy(_items,1)"> 399  400 
 401          Ensures that the capacity of this list is at least the given minimum
 402          value. If the currect capacity of the list is less than min,1)"> 403          capacity is increased to twice the current capacity or to min, 404          whichever is larger.
 405         void EnsureCapacity( min) {
 406             if (_items.Length < 407                 int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2 408                  Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
 409                  Note that this check works even when _items.Length overflowed thanks to the (uint) cast
 410                 uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
 411                 if (newCapacity < min) newCapacity = min;
 412                 Capacity = newCapacity;
 413  414  415    
 416         bool Exists(Predicate<T> match) {
 417             return FindIndex(match) != - 418  419 
 420         public T Find(Predicate<T> 421             if( match ==  422                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
 423  424  425 
 426             0 ; i < _size; i++ 427                 (match(_items[i])) {
 428                      _items[i];
 429  430  431             default(T);
 432  433   
 434         public List<T> FindAll(Predicate<T> match) { 
 435              436  437  438  439 
 440             List<T> list = new List<T>(); 
 441              442                  443                     list.Add(_items[i]);
 444  445  446              447  448   
 449         int FindIndex(Predicate<T> 450             Contract.Ensures(Contract.Result<int>() >= - 451             Contract.Ensures(Contract.Result<int>() < 452             return FindIndex( 453  454   
 455         int FindIndex(int startIndex,Predicate<T> 456             Contract.Ensures(Contract.Result< 457             Contract.Ensures(Contract.Result<int>() < startIndex + 458             return FindIndex(startIndex,_size - startIndex,1)"> 459  460  
 461          462             if( (uint)startIndex > ()_size ) {
 463                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex,ExceptionResource.ArgumentOutOfRange_Index);                
 464  465 
 466             0 || startIndex > _size - 467  468  469 
 470              471  472  473             Contract.Ensures(Contract.Result< 474             Contract.Ensures(Contract.Result< 475  476 
 477             int endIndex = startIndex + 478             int i = startIndex; i < endIndex; i++ 479                 if( match(_items[i]))  i;
 480  481             return - 482  483  
 484         public T FindLast(Predicate<T> 485              486  487  488  489 
 490             int i = _size - 1 ; i >= 0; i-- 491                  492                      493  494  495              496  497 
 498         int FindLastIndex(Predicate<T> 499             Contract.Ensures(Contract.Result< 500             Contract.Ensures(Contract.Result< 501             return FindLastIndex(_size -  502  503    
 504         int FindLastIndex( 505             Contract.Ensures(Contract.Result< 506             Contract.Ensures(Contract.Result< startIndex);
 507             return FindLastIndex(startIndex,startIndex +  508  509 
 510          511              512  513  514             Contract.Ensures(Contract.Result< 515             Contract.Ensures(Contract.Result< 516  517 
 518             if(_size ==  519                  Special case for 0 length List
 520                 if( startIndex != - 521                     ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex,ExceptionResource.ArgumentOutOfRange_Index);
 522  523  524              525                  Make sure we're not out of range            
 526                 if ( (uint)startIndex >= ( 527  528  529  530             
 531              2nd have of this also catches when startIndex == MAXINT,so MAXINT - 0 + 1 == -1,which is < 0.
 532             0 || startIndex - count + 1 <  533  534  535                         
 536             int endIndex = startIndex - 537             int i = startIndex; i > endIndex; i-- 538                 ( match(_items[i])) {
 539                      540  541  542              543  544 
 545         void ForEach(Action<T> action) {
 546             if( action ==  547  548  549  550 
 551             int version = 552 
 553              554                 if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) {
 555                     break 556  557                 action(_items[i]);
 558  559 
 560              BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
 561                 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
 562  563 
 564          Returns an enumerator for this list with the given
 565          permission for removal of elements. If modifications made to the list 
 566          while an enumeration is in progress,the MoveNext and 
 567          GetObject methods of the enumerator will throw an exception.
 568          569          Enumerator GetEnumerator() {
 570             new Enumerator( 571  572 
 573         /// <internalonly/>
 574         IEnumerator<T> IEnumerable<T>.GetEnumerator() {
 575              576  577 
 578         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
 579              580  581 
 582         public List<T> GetRange( 583              584  585  586 
 587              588  589  590 
 591              592                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);                
 593  594             Contract.Ensures(Contract.Result<List<T>>() !=  595  596 
 597             List<T> list = (count);
 598             Array.Copy(_items,list._items,count);            
 599             list._size = 600              601  602 
 603 
 604          Returns the index of the first occurrence of a given value in a range of
 605          this list. The list is searched forwards from beginning to end.
 606          The elements of the list are compared to the given value using the
 607          Object.Equals method.
 608          609          This method uses the Array.IndexOf method to perform the
 610          611          612          IndexOf(T item) {
 613             Contract.Ensures(Contract.Result< 614             Contract.Ensures(Contract.Result< 615             return Array.IndexOf(_items,1)"> 616  617 
 618          System.Collections.IList.IndexOf(Object item)
 619  620              621                  IndexOf((T)item);
 622  623              624  625 
 626          627          this list. The list is searched forwards,starting at index
 628          index and ending at count number of elements. The
 629          elements of the list are compared to the given value using the
 630          631          632          633          634          635         int IndexOf(T item,1)"> index) {
 636             if (index > _size)
 637  638             Contract.Ensures(Contract.Result< 639             Contract.Ensures(Contract.Result< 640  641              index);
 642  643 
 644          645          646          index and upto count number of elements. The
 647          648          649          650          651          652          653          654              655  656 
 657             if (count <0 || index > _size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count,1)"> 658             Contract.Ensures(Contract.Result< 659             Contract.Ensures(Contract.Result< 660  661 
 662              Array.IndexOf(_items,1)"> 663  664     
 665          Inserts an element into this list at a given index. The size of the list
 666          is increased by one. If required,1)"> 667          before inserting the new element.
 668          669         void Insert( index,T item) {
 670              Note that insertions at the end are legal.
 671             uint) index > ( 672  673  674  675              676             if (index < 677                 Array.Copy(_items,_items,index + 1,1)"> 678  679             _items[index] = 680             _size++;            
 681             _version++ 682  683     
 684         void System.Collections.IList.Insert( 685  686             ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T> 687 
 688              689                 Insert(index,(T) item);
 690  691              692                 ThrowHelper.ThrowWrongValueTypeArgumentException(item,1)"> 693  694  695 
 696          Inserts the elements of the given collection at a given index. If
 697          698          699          to the end of the list by setting index to the List's size.
 700          701         void InsertRange( 702              703  704  705             
 706             uint)index > ( 707  708  709  710 
 711             ICollection<T> c = collection  712             null ) {     if collection is ICollection<T>
 713                  714                 if (count >  715                     EnsureCapacity(_size + 716                      717                         Array.Copy(_items,index + count,1)"> 718  719                     
 720                      If we're inserting a List into itself,we want to be able to deal with that.
 721                     if (this == c) {
 722                          Copy first part of _items to insert location
 723                         Array.Copy(_items,index);
 724                          Copy last part of _items back to inserted location
 725                         Array.Copy(_items,index+count,index*2,_size-index);
 726  727                      728                         T[] itemsToInsert =  729                         c.CopyTo(itemsToInsert,1)"> 730                         itemsToInsert.CopyTo(_items,index);                    
 731  732                     _size += 733                 }                
 734  735              736                  737                      738                         Insert(index++ 739                     }                
 740  741  742             _version++ 743  744     
 745          Returns the index of the last occurrence of a given value in a range of
 746          this list. The list is searched backwards,starting at the end 
 747          and ending at the first element in the list. The elements of the list 
 748          are compared to the given value using the Object.Equals method.
 749          750          This method uses the Array.LastIndexOf method to perform the
 751          752          753          LastIndexOf(T item)
 754  755             Contract.Ensures(Contract.Result< 756             Contract.Ensures(Contract.Result< 757             if (_size == 0) {   Special case for empty list
 758                  759  760              761                 return LastIndexOf(item,_size -  762  763  764 
 765          766          767          index and ending at the first element in the list. The 
 768          elements of the list are compared to the given value using the 
 769          770          771          772          773          774         int LastIndexOf(T item,1)"> index)
 775  776             if (index >= 777  778             Contract.Ensures(Contract.Result< 779             Contract.Ensures(((Count == 0) && (Contract.Result<int>() == -1)) || ((Count >  index)));
 780  781              782  783 
 784          785          786          index and upto count elements. The elements of
 787          the list are compared to the given value using the Object.Equals
 788          method.
 789          790          791          792          793          794             if ((Count != 0) && (index <  795  796  797 
 798             if ((Count !=0) && (count <  799  800  801             Contract.Ensures(Contract.Result< 802             Contract.Ensures(((Count ==  803  804 
 805              806                  807  808 
 809              810  811  812 
 813             if (count > index +  814  815             } 
 816 
 817              Array.LastIndexOf(_items,1)"> 818  819     
 820          Removes the element at the given index. The size of the list is
 821          decreased by one.
 822          823          Remove(T item) {
 824             int index = IndexOf(item);
 825             if (index >=  826                 RemoveAt(index);
 827                  828  829 
 830              831  832 
 833          System.Collections.IList.Remove(Object item)
 834  835              836                 Remove((T) item);
 837  838  839 
 840          This method removes all items which matches the predicate.
 841          The complexity is O(n).   
 842         int RemoveAll(Predicate<T> 843              844  845  846             Contract.Ensures(Contract.Result< 847             Contract.Ensures(Contract.Result< 848  849     
 850             int freeIndex = 0;    the first free slot in items array
 851 
 852              Find the first item which needs to be removed.
 853             while( freeIndex < _size && !match(_items[freeIndex])) freeIndex++ 854             if( freeIndex >= _size) return  855             
 856             int current = freeIndex +  857             while( current < 858                  Find the first item which needs to be kept.
 859                 while( current < _size && match(_items[current])) current++ 860 
 861                 if( current < 862                      copy item to the free slot.
 863                     _items[freeIndex++] = _items[current++];
 864  865             }                       
 866             
 867             Array.Clear(_items,freeIndex,1)"> freeIndex);
 868             int result = _size - freeIndex;
 869             _size = 870             _version++ 871              result;
 872  873 
 874          875          876          877         void RemoveAt( 878             uint)index >= ( 879                 ThrowHelper.ThrowArgumentOutOfRangeException();
 880  881  882             _size-- 883              884                 Array.Copy(_items,1)"> 885  886             _items[_size] =  887             _version++ 888  889     
 890          Removes a range of elements from this list.
 891          892         void RemoveRange( 893              894  895  896 
 897              898  899  900                 
 901              902  903  904     
 905              906                 int i = 907                 _size -= 908                  909                     Array.Copy(_items,1)"> 910  911                 Array.Clear(_items,1)"> 912                 _version++ 913  914  915     
 916          Reverses the elements in this list.
 917          Reverse() {
 918             Reverse( 919  920     
 921          Reverses the elements in a range of this list. Following a call to this
 922          method,an element in the range given by index and count
 923          which was previously located at index i will now be located at
 924          index index + (index + count - i - 1).
 925          926          This method uses the Array.Reverse method to reverse the
 927          elements.
 928          929         void Reverse( 930              931  932  933                 
 934              935  936  937 
 938              939  940  941             Array.Reverse(_items,1)"> 942             _version++ 943  944         
 945          Sorts the elements in this list.  Uses the default comparer and 
 946          Array.Sort.
 947          Sort()
 948  949             Sort( 950  951 
 952          Sorts the elements in this list.  Uses Array.Sort with the
 953          provided comparer.
 954         void Sort(IComparer<T> 955  956             Sort( 957  958 
 959          Sorts the elements in a section of this list. The sort compares the
 960          elements to each other using the given IComparer interface. If
 961          comparer is null,the elements are compared to each other using
 962          the IComparable interface,which in that case must be implemented by all
 963          elements of the list.
 964          965          This method uses the Array.Sort method to sort the elements.
 966          967         void Sort( 968              969  970  971             
 972              973  974  975                 
 976              977  978  979 
 980             Array.Sort<T> 981             _version++ 982  983 
 984         void Sort(Comparison<T> comparison) {
 985             if( comparison ==  986  987  988  989 
 990             if( _size >  991                 IComparer<T> comparer = new Array.FunctorComparer<T>(comparison);
 992                 Array.Sort(_items,1)"> 993  994  995 
 996          ToArray returns a new Object array containing the contents of the List.
 997          This requires copying the List,which is an O(n) operation.
 998          T[] ToArray() {
 999             Contract.Ensures(Contract.Result<T[]>() != 1000             Contract.Ensures(Contract.Result<T[]>().Length ==1001 
1002             T[] array =  T[_size];
1003             Array.Copy(_items,1)">1004              array;
1005 1006     
1007          Sets the capacity of this list to the size of the list. This method can
1008          be used to minimize a list's memory overhead once it is known that no
1009          new elements will be added to the list. To completely clear a list and
1010          release all memory referenced by the list,execute the following
1011          statements:
1012         1013          list.Clear();
1014          list.TrimExcess();
1015         1016          TrimExcess() {
1017             int threshold = (int)(((double)_items.Length) * 0.9);             
1018             if( _size < threshold ) {
1019                 Capacity = _size;                
1020 1021         }    
1022 
1023         bool TrueForAll(Predicate<T>1024             1025 1026 1027 1028 
1029             1030                 if( !match(_items[i])) {
1031                     1032 1033 1034             1035         } 
1036 
1037         internal static IList<T> Synchronized(List<T> list) {
1038              SynchronizedList(list);
1039 1040 
1041         [Serializable()]
1042         class SynchronizedList : IList<T>1043             private List<T> _list;
1044              Object _root;
1045     
1046             internal SynchronizedList(List<T>1047                 _list =1048                 _root = ((System.Collections.ICollection)list).SyncRoot;
1049 1050 
1051             1052                 1053                     lock (_root) { 
1054                          _list.Count; 
1055 1056 1057 1058 
1059              IsReadOnly {
1060                 1061                     return ((ICollection<T>)_list).IsReadOnly;
1062 1063 1064 
1065             1066                 1067                     _list.Add(item); 
1068 1069 1070 
1071             1072                 1073                     _list.Clear(); 
1074 1075 1076 
1077             1078                 1079                      _list.Contains(item);
1080 1081 1082 
1083             1084                 1085                     _list.CopyTo(array,arrayIndex);
1086 1087 1088 
1089             1090                 1091                      _list.Remove(item);
1092 1093 1094 
1095             System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
1096                 1097                      _list.GetEnumerator();
1098 1099 1100 
1101             IEnumerator<T> IEnumerable<T>1102                 1103                     return ((IEnumerable<T>)_list).GetEnumerator();
1104 1105 1106 
1107             1108                 1109                     (_root) {
1110                          _list[index];
1111 1112 1113                 1114                     1115                         _list[index] =1116 1117 1118 1119 
1120             1121                  (_root) {
1122                      _list.IndexOf(item);
1123 1124 1125 
1126             1127                 1128                     _list.Insert(index,item);
1129 1130 1131 
1132             1133                 1134                     _list.RemoveAt(index);
1135 1136 1137 1138 
1139         [Serializable]
1140         struct Enumerator : IEnumerator<T>1141 1142             1143              index;
1144              version;
1145              T current;
1146 
1147             internal Enumerator(List<T>1148                 this.list =1149                 index = 1150                 version = list._version;
1151                 current = 1152 1153 
1154              Dispose() {
1155 1156 
1157              MoveNext() {
1158 
1159                 List<T> localList =1160 
1161                 if (version == localList._version && ((uint)index < ()localList._size)) 
1162                 {                                                     
1163                     current = localList._items[index];                    
1164                     index++1165                     1166 1167                  MoveNextRare();
1168 1169 
1170              MoveNextRare()
1171             {                
1172                 if (version != list._version) {
1173                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
1174 1175 
1176                 index = list._size + 1177                 current = 1178                 ;                
1179 1180 
1181              T Current {
1182                 1183                      current;
1184 1185 1186 
1187             Object System.Collections.IEnumerator.Current {
1188                 1189                     if( index == 0 || index == list._size + 1190                          ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
1191 1192                      Current;
1193 1194 1195     
1196              System.Collections.IEnumerator.Reset() {
1197                 1198 1199 1200                 
1201                 index = 1202                 current = 1203 1204 
1205 1206     }
1207 }
View Code

创建一个Account类

 1 class Account
 2  3         string Name { get;  4         decimal Balance {  5 
 6         public Account(string name,Decimal balance)
 7  8             this.Name = name;
 9             this.Balance = balance;
10 11     }

 

创建一个Account类的集合LIst:

1 var account = new List<Account>()
2 3                 new Account(Christian",1)">1500),1)">4                 Stephanie22005                 Angela18006                 Matthias24007             };

 

跟踪代码可见:

1、通过List类的构造函数创建一个模板类型T(Account)的数组:

2             
3         4         5         6         7             _items =8         }

 

2、创建Account 对象(略)

3、调用List类的Add方法。

2             3             _items[_size++] =4             _version++5         }

 

 1 // 确保该列表的容量至少是给定的最小值。如果列表的currect容量小于min,容量将增加到当前容量的两倍或最小,无论哪个更大。
 5         private void EnsureCapacity(int min) {
 6             if (_items.Length < min) {
 7                 int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;//_defaultCapacity =4
 8                 // 允许列表在遇到溢出之前增加到最大容量(~ 2G元素)。
 9                 // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
10                 if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;//Arrat,NaxArrayLength = 2146435071
11                 if (newCapacity < min) newCapacity = min;
12                 Capacity = newCapacity;//=>
13             }
14         }
 2              3                 Contract.Ensures(Contract.Result< 4                  5  6              7                  8  9 11 
12                 13                     14                         T[] newItems = 15                         16                             Array.Copy(_items,1)">17 18                         _items =19 20                     21                         _items =22 23 24 25         }

 

未多解释,直接上的代码,通过上面的代码可以看出其实List的实现,是同过T[]数组实现的。

还未深掘泛型的实现。研究中。。。

相关文章

引言 本文从Linux小白的视角, 在CentOS 7.x服务器上搭建一个...
引言: 多线程编程/异步编程非常复杂,有很多概念和工具需要...
一. 宏观概念 ASP.NET Core Middleware是在应用程序处理管道...
背景 在.Net和C#中运行异步代码相当简单,因为我们有时候需要...
HTTP基本认证 在HTTP中,HTTP基本认证(Basic Authenticatio...
1.Linq 执行多列排序 OrderBy的意义是按照指定顺序排序,连续...