日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#List源码

發(fā)布時間:2024/4/15 C# 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#List源码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • List
  • // C# 源碼

    public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>

    {

    ??? private const int _defaultCapacity = 4;//默認容量為4

    ?

    ??? private T[] _items;//list內(nèi)部是用數(shù)組實現(xiàn)的

    ??? [ContractPublicPropertyName("Count")]

    ??? private int _size;

    ??? private int _version;//在遍歷時如果發(fā)現(xiàn)_version變了立即退出并拋出遍歷過程集合被修改異常,比如在foreach里remove或add元素就會導致這個異常。更常見的是出現(xiàn)在多線程時一個線程遍歷集合,另一個線程修改集合的時候,相信很多人吃過苦頭。

    ??? [NonSerialized]

    ??? private Object _syncRoot;

    ?

    ??? static readonly T[]? _emptyArray = new T[0];???????

    ?

    ??? // 其他內(nèi)容???

    ?}

    ???? // C# Code

    // Adds the given object to the end of this list. The size of the list is

    // increased by one. If required, the capacity of the list is doubled

    // before adding the new element.

    //

    ?

    //擴容時翻倍

    public void Add(T item) {

    ??? if (_size == _items.Length)

    ??????? EnsureCapacity(_size + 1);

    ??? _items[_size++] = item;

    ??? _version++;

    }

    ?

    // Ensures that the capacity of this list is at least the given minimum

    // value. If the currect capacity of the list is less than min, the

    // capacity is increased to twice the current capacity or to min,

    // whichever is larger.

    private void EnsureCapacity(int min) {

    ??? if (_items.Length < min) {

    ??????? int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;

    ??????? // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.

    ??????? // Note that this check works even when _items.Length overflowed thanks to the (uint) cast

    ??????? if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;

    ??????? if (newCapacity < min) newCapacity = min;

    ??????? Capacity = newCapacity;

    ??? }

    }

    ?

    // Gets and sets the capacity of this list.? The capacity is the size of

    // the internal array used to hold items.? When set, the internal

    // array of the list is reallocated to the given capacity.

    //

    public int Capacity {

    ??? get {

    ??????? Contract.Ensures(Contract.Result<int>() >= 0);

    ??????? return _items.Length;

    ??? }

    ??? set {

    ??????? if (value < _size) {

    ??????????? ThrowHelper.ThrowArgumentOutOfRangeException(

    ??????????????? ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);

    ??????? }

    ??????? Contract.EndContractBlock();

    ?

    ??????? if (value != _items.Length) {

    ??????????? if (value > 0) {

    ??????????????? T[] newItems = new T[value];

    ??????????????? if (_size > 0) {

    ??????????????????? Array.Copy(_items, 0, newItems, 0, _size);

    ??????????????? }

    ??????????????? _items = newItems;

    ??????????? }

    ??????? ????else {

    ??????????????? _items = _emptyArray;

    ??????????? }

    ??????? }

    ??? }

    }

    C# 中 List默認的容量其實是4,所以最好還是初始化容量吧,可以想象,如果一個列表里面有129個元素,那么代碼中對Capacity的調(diào)用會有很多次,4->8->16->32->64->128->256,不但最后的容量中產(chǎn)生了大量的浪費,前面的一堆對象也都需要GC搞定了。也就是252個對象。浪費還是很嚴重的。

    // Removes the element at the given index. The size of the list is

    // decreased by one.

    public bool Remove(T item) {

    ??? int index = IndexOf(item);

    ??? if (index >= 0) {

    ??????? RemoveAt(index);

    ??????? return true;

    ??? }

    ?

    ??? return false;

    }

    ?

    // Returns the index of the first occurrence of a given value in a range of

    // this list. The list is searched forwards from beginning to end.

    // The elements of the list are compared to the given value using the

    // Object.Equals method.

    //

    // This method uses the Array.IndexOf method to perform the

    // search.

    //

    public int IndexOf(T item) {

    ??? Contract.Ensures(Contract.Result<int>() >= -1);

    ??? Contract.Ensures(Contract.Result<int>() < Count);

    ??? return Array.IndexOf(_items, item, 0, _size);

    }

    ?

    // Array.cs

    public static int IndexOf<T>(T[] array, T value, int startIndex, int count) {

    ??? if (array==null) {

    ??????? throw new ArgumentNullException("array");

    ??? }

    ?

    ??? if (startIndex < 0 || startIndex > array.Length ) {

    ??????? throw new ArgumentOutOfRangeException("startIndex",

    ??????????? Environment.GetResourceString("ArgumentOutOfRange_Index"));

    ??? }

    ?

    ??? if (count < 0 || count > array.Length - startIndex) {

    ?? ?????throw new ArgumentOutOfRangeException("count",

    ??????????? Environment.GetResourceString("ArgumentOutOfRange_Count"));

    ??? }

    ??? Contract.Ensures(Contract.Result<int>() < array.Length);

    ??? Contract.EndContractBlock();

    ?

    ??? return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);

    }

    ?

    // Removes the element at the given index. The size of the list is

    // decreased by one.

    public void RemoveAt(int index) {

    ??? if ((uint)index >= (uint)_size) {

    ??????? ThrowHelper.ThrowArgumentOutOfRangeException();

    ??? }

    ??? Contract.EndContractBlock();

    ??? _size--;

    ??? if (index < _size) {

    ??????? Array.Copy(_items, index + 1, _items, index, _size - index);

    ??? }

    ??? _items[_size] = default(T);

    ??? _version++;

    }

    從代碼來看,remove操作優(yōu)先看的是能否找到該元素,如果能找到,將其移除,返回True,否則,返回false

    C#的索引方法有點復雜,點到EqualityComparer里面看了一下索引的方法,這也是C#跟Java的不同之處了,Java的泛型里面是不能寫入Primitive類型的,因為Primitive類型其實是不繼承Object的,所以無法調(diào)用其中的equals方法。

    但是C#是支持的,所以,會判斷元類型的Type,然后選取對應的Equals方法。

    ?

    現(xiàn)在回頭看下RemoveAt方法,該方法仍然會調(diào)用Array.Copy操作,所以,可想而知刪除操作的復雜度了,內(nèi)存中平均刪除一個元素,要移動n/2個元素,復雜度為O(n)

    ?

    而RemoveAll方法本身是復雜度為O(n)的,所以最好不要在循環(huán)中寫Remove操作吧。

    轉載于:https://www.cnblogs.com/mcyushao/p/10629611.html

    總結

    以上是生活随笔為你收集整理的C#List源码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。