.NET Core CSharp 中級篇 2-2
本節(jié)內(nèi)容為List,ArrayList,和Dictionary
簡介
在此前的文章中我們學(xué)習(xí)了數(shù)組的使用,但是數(shù)組有一個很大的問題就是存儲空間不足,我們通常的解決方法就是定義一個絕對夠用的數(shù)組,這通常很大,但是這樣就造成了內(nèi)存的損失。我們總是希望有一個根據(jù)需求動態(tài)更變的數(shù)組進(jìn)行存儲。在上一節(jié)中的綜合題中已經(jīng)隱隱約約引出了List的概念。這一講我們會詳細(xì)的講解List。
同時(shí),有時(shí)候我們希望數(shù)組不單單的存儲我們的數(shù)據(jù)。例如我希望有那么一些數(shù)據(jù):
某人的成績單如下:
* 語文 80分
* 數(shù)學(xué) 90分
* 英語 87分
對于這些數(shù)據(jù),我們使用數(shù)組并不能很好的反饋這些成績,這個時(shí)候我們需要使用我們的字典進(jìn)行存儲。
List、ArrayList
ArrayList
正如上文所言,數(shù)組是一段連續(xù)存儲空間,訪問速度非常快,但是必須指定大小,這個時(shí)候我們可以使用ArrayList進(jìn)行使用。ArrayList是位于System.Collections的一個類,繼承與IList接口,提供了數(shù)據(jù)的操作。它比數(shù)組更優(yōu)的地方是,它不需要指定任何的大小和類型,直接使用即可。
ArrayList al = new ArrayList(); al.Add("test"); al.Add(1234); //修改數(shù)據(jù) al[1] =
4; //移除數(shù)據(jù) al.RemoveAt(0); //插入數(shù)據(jù) al.Insert(0, "qwe");
看起來非常好用對吧,可以插入不同數(shù)據(jù)并且修改。但是其實(shí)這是非常損失性能的一個操作。因?yàn)樵贏rrayList中插入不同類型的數(shù)據(jù)是是允許的,但是在處理后續(xù)數(shù)據(jù)的時(shí)候,ArrayList會將內(nèi)部所有的數(shù)據(jù)當(dāng)成Object類型進(jìn)行處理,因此在每一個數(shù)據(jù)進(jìn)行遍歷的時(shí)候,都會發(fā)生裝箱與拆箱的操作,在上一講我們討論過,頻繁的裝拆箱是極其損耗性能的。因此,ArrayList在實(shí)際情況下并不經(jīng)常使用。
泛型List
為了解決ArrayList中類型不同導(dǎo)致的不安全和裝拆箱,我們使用泛型List類。List類是ArrayList類的泛型等效類,它的大部分用法都與ArrayList相似,因?yàn)長ist類也繼承了IList接口。最關(guān)鍵的區(qū)別在于,在聲明List集合時(shí),我們同時(shí)需要為其聲明List集合內(nèi)數(shù)據(jù)的對象類型,也就是泛型參數(shù)。我們在
初級篇的綜合習(xí)題中已經(jīng)隱約引出了關(guān)于List的部分內(nèi)容。對于List,它的定義如下:
List<T> list = new List<T>(); list.Add(new T()); list[0]; list.Remove(T);
對于List,它實(shí)現(xiàn)了一個非常重要的接口——IEnumerable,這意味著List支持使用foreach循環(huán)進(jìn)行遍歷內(nèi)部元素。不過使用foreach的時(shí)候,下列操作時(shí)不合法的:
foreach(var item in MyList) { MyList.Remove(item);//不過我相信沒有人那么干,但是....
//這種操作我不止一次見過有人問我 if(item.something == something) { MyList.Remove(item); } }
這個時(shí)候,你需要往回仔細(xì)的回憶我們之前foreach循環(huán)的講解,在foreach循環(huán)中通過這種方式動態(tài)的刪除一個元素是不合法的,為什么?因?yàn)閒oreach循環(huán)會調(diào)用MoveNext()方法,你可以想象一下一個節(jié)點(diǎn)連著一個節(jié)點(diǎn)成為了一串集合體,你每次只能向后訪問一個節(jié)點(diǎn),也就意味著你必須知曉前一個節(jié)點(diǎn)才可以訪問后一個節(jié)點(diǎn),假設(shè)你訪問到某節(jié)點(diǎn)的時(shí)候,你刪除了它,那么后續(xù)的節(jié)點(diǎn)訪問都無法被訪問。有沒有解決的方法呢?當(dāng)然有,但是你只能使用for循環(huán),List中有一個屬性叫做Count,這個代表著當(dāng)前List中所擁有的所有元素的個數(shù),并且List實(shí)現(xiàn)了索引器,也就是說,List可以通過類似于MyList[0]的方式訪問,這個時(shí)候,你使用for循環(huán)動態(tài)刪除應(yīng)當(dāng)如下:
for(int i =0;i<MyList.Count;i++) { if(MyList[i].something == something) {
MyList.Remove(MyList[i]); } }
Dictionary字典
你肯定有過簡介中提到過的需求。很多時(shí)候單純的索引值沒有辦法給我們提供更多的信息,我們總是傾向于使用一個鍵值對的方式進(jìn)行存儲數(shù)據(jù)。那么Dictionary將會很好的解決你的問題。它的基本結(jié)構(gòu)是由兩個泛型參數(shù)進(jìn)行修飾,Dictionary<TKey,TValue>,前面是鍵的類型,后面是值的類型,你也可以把Dictionary理解成一種特殊的集合。它的使用如下:
Dictionary<string,string> dict = new Dictionary<string,string>();
dict.Add("廣東","廣州"); dict.Add("江西","南昌"); dict["江西"]; dict.remove("廣東");
通常來說,我們很少使用foreach直接訪問Dictionary,因?yàn)榈慕Y(jié)果就是一個個鍵值對,一般Dictionary的Value以List居多,因此一般都是迭代Key。
Dictionary大部分操作和List是接近的,這里就不過多闡述。
IEnumerable與IList接口
這兩個接口時(shí)集合(List)的實(shí)現(xiàn)的重要接口,IEnumerable提供了迭代功能,IList提供了相應(yīng)的集合操作,我們從元數(shù)據(jù)中就可以很好的學(xué)習(xí)他們。
IEnumerable接口
它在元數(shù)據(jù)的定義如下:
public interface IEnumerable<out T> : IEnumerable { // // 摘要: // Returns an
enumerator that iterates through the collection. // // 返回結(jié)果: // An enumerator
that can be used to iterate through the collection. IEnumerator<T>
GetEnumerator(); }
我們可以很清楚的發(fā)現(xiàn)泛型參數(shù)中有out關(guān)鍵字修飾,也就是說,我們的IEnumerable是支持協(xié)變的。我們可以很輕松的將IEnumerable類型的數(shù)據(jù)轉(zhuǎn)換成其他數(shù)據(jù),例如:
IEnumerable<string> strs = new IEnumerable<string>(); IEnumerable<object> obj
= strs;
因此我通常在使用的時(shí)候,我會推薦使用IEnumerable來代替List的一些數(shù)據(jù)操作。
IList接口
老規(guī)矩,先看看元數(shù)據(jù)
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable {
//省略 }
這里就可以發(fā)現(xiàn)IList并不支持協(xié)變,屬于不變式,那么下列用法是不合法的:
IList<string> strs = new IList<string>(); IList<object> obj = strs;
如果我的文章幫助了您,請您在github .NET Core Guide項(xiàng)目幫我點(diǎn)一個star,在博客園中點(diǎn)一個關(guān)注和推薦。
Github <https://github.com/StevenEco/.NetCoreGuide>
BiliBili主頁 <https://space.bilibili.com/33311288>
WarrenRyan's Blog <https://blog.tity.xyz/>
博客園 <https://cnblogs.com/warrenryan>
熱門工具 換一換