C#中List<T>存放元素的工作機(jī)制
List<T>是怎么存放元素?我們扒一段List<T>的一段源碼來一窺究竟。
using System;
using System.Diagnostic;
using System.Collections.ObjectModel;
using System.Security.Permissions;
namespace System.Collections.Generic
{
...
[Serializable()]
public class List<t> : IList<t>, System.Collections.IList
{
private const int _defaultCapacity = 4;
private T[] _items; //List<T>內(nèi)部是依靠數(shù)組_items存放數(shù)據(jù)的
private int _size; //數(shù)組的長(zhǎng)度
private int _version;
[NoSerialized]
private Object _syncRoot;
static T[] _emptyArray = new T[0];
//無參數(shù)構(gòu)造函數(shù) 把_items設(shè)置成一個(gè)空的數(shù)組
public List()
{
_items = _emptyArray;
}
//此構(gòu)造函數(shù) 給_items數(shù)組一個(gè)初始容量
public List(int capacity)
{
...
items = new T[capaicty];
}
//此構(gòu)造函數(shù) 把集合類型參數(shù)拷貝給_items數(shù)組
public List(IEnumerable<t> collection)
{
...
ICollection<t> c = collection as ICollection<t>;
if(c != null)
{
int count = c.Count; //把構(gòu)造函數(shù)集合類型參數(shù)的長(zhǎng)度賦值給臨時(shí)變量count
_items = new T[count]; //List<T>內(nèi)部維護(hù)的_items數(shù)組的長(zhǎng)度和構(gòu)造函數(shù)集合類型參數(shù)的長(zhǎng)度一致
c.CopyTo(_items, 0); //把構(gòu)造函數(shù)集合的所有元素拷貝到_items數(shù)組中去
_size = count; //_items數(shù)組的長(zhǎng)度就是構(gòu)造函數(shù)集合類型參數(shù)的長(zhǎng)度
}
else
{
_size = 0;
_items = new T[_defaultCapacity];
...
}
}
//通過設(shè)置這個(gè)屬性,改變List<t>內(nèi)部維護(hù)的_items數(shù)組的長(zhǎng)度
public int Capacity
{
get {return _items.Length; }
set {
if(value != _items.Length){ //如果當(dāng)前賦值和List<t>維護(hù)的內(nèi)部數(shù)組_items長(zhǎng)度不一致
if(value < _size){
//TODO: 處理異常
}
if(value > 0){
T[] newItems = new T[value]; //創(chuàng)建一個(gè)臨時(shí)的、新的數(shù)組,長(zhǎng)度為新的賦值
if(_size > 0){
//把臨時(shí)的、新的數(shù)組拷貝給List<t>內(nèi)部維護(hù)的數(shù)組_items,注意,這時(shí)_items的長(zhǎng)度為新的賦值
Array.Copy(_items, 0, newItems, 0, _size);
}
} else {
_items = _emptyArray;
}
}
}
}
public void Add(T item)
{
if(_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size++] = item;
...
}
//確保List<t>內(nèi)部維護(hù)的_items數(shù)組的長(zhǎng)度至少是給定的值
//如果_items數(shù)組原先的長(zhǎng)度比給定的值小,就讓_items數(shù)組的長(zhǎng)度設(shè)置為原先的長(zhǎng)度的2倍
privat void EnsureCapacity(int min)
{
if(_items.Length < min){
int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Legnth * 2;
if(newCapacity < min) newCapacity = min;
Capacity = newCapacity;
}
}
}
}由此可見,向List<T>中存放元素的大致過程是這樣的:
- List<T>內(nèi)部維護(hù)著一個(gè)數(shù)組_items,用來存放T類型的元素。
- 當(dāng)有新的T類型元素存放進(jìn)來,即調(diào)用Add(T item)方法。
- Add(T item)方法內(nèi)部調(diào)用EnsureCapacity(int min)方法確保List<T>的Capaicty屬性值至少在原先長(zhǎng)度上加1,最多是原先長(zhǎng)度的2倍。
- 在給Capacity賦值的過程中,對(duì)_items的長(zhǎng)度進(jìn)行了擴(kuò)容。
- 擴(kuò)容后,再把新的T類型元素存放進(jìn)來。
簡(jiǎn)單地說:
當(dāng)有新的元素存放到List<T>中時(shí),List<T>先對(duì)其維護(hù)的內(nèi)部數(shù)組進(jìn)行擴(kuò)容,然后再把新元素放進(jìn)來。
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
C#RSA對(duì)接JAVA中RSA方式代碼實(shí)例
在本篇文章中小編給各位整理的是關(guān)于C#RSA對(duì)接JAVA中RSA方式代碼實(shí)例,有需要的朋友們可以參考一下。2019-09-09
深入U(xiǎn)nix時(shí)間戳與C# DateTime時(shí)間類型互換的詳解
本篇文章是對(duì)Unix時(shí)間戳與C# DateTime時(shí)間類型互換進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
C#優(yōu)化if...else代碼的方案總結(jié)
在編寫代碼實(shí)現(xiàn)業(yè)務(wù)需求過程中,會(huì)使用到大量的if...else 判斷語句,隨業(yè)務(wù)復(fù)雜程度不同,導(dǎo)致判斷語句出現(xiàn)多層嵌套、多分支等情況,導(dǎo)致代碼可讀性變差、增加維護(hù)難度,本文介紹了C# 如何優(yōu)化 if...else 讓代碼優(yōu)雅起來,需要的朋友可以參考下2024-06-06
c#linq里的Skip和Take實(shí)現(xiàn)分頁或遍歷
LINQ的優(yōu)勢(shì)在于它提供了一種直觀、類型安全的方式來操作各種類型的數(shù)據(jù),查詢常需要獲取一部分?jǐn)?shù)據(jù),為了實(shí)現(xiàn)這一功能,LINQ提供了Take?和Skip運(yùn)算符,Take運(yùn)算符用于從一個(gè)序列中返回指定個(gè)數(shù)的元素,Skip運(yùn)算符用于從一個(gè)序列中跳過指定個(gè)數(shù)的元素2024-01-01
詳解C#中對(duì)于接口的實(shí)現(xiàn)方式(隱式接口和顯式接口)
這篇文章主要介紹了詳解C#中對(duì)于接口的實(shí)現(xiàn)方式(隱式接口和顯式接口),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
visio二次開發(fā)--判斷文檔是否已發(fā)生變化(變化就加星號(hào)*)
最近做一個(gè)故障樹診斷的項(xiàng)目,用visio二次開發(fā),可以同時(shí)打開多個(gè)繪制的故障樹圖形文檔。項(xiàng)目中需要實(shí)現(xiàn)判斷文檔是否發(fā)生變化,這是很多編輯軟件的基本功能,變化了就加個(gè)星號(hào)*2013-04-04
C#學(xué)習(xí)教程之Socket的簡(jiǎn)單使用
這篇文章主要給大家介紹了關(guān)于C#學(xué)習(xí)教程之Socket的簡(jiǎn)單使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02

