.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 }
创建一个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 对象(略)
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[]数组实现的。
还未深掘泛型的实现。研究中。。。
原文链接:/aspnet/994767.html