最近狀態(tài)有點(diǎn)不對(duì),所以就沒有去更新筆記,塔防游戲也沒繼續(xù)開發(fā),等調(diào)整好狀態(tài)再繼續(xù)塔防游戲。
先做一些筆記找找感覺,估計(jì)是真的老了,內(nèi)分泌失調(diào),各種不順心。。。
繼續(xù)關(guān)于泛型的記錄,上一篇中記錄了一些在MSDN中學(xué)習(xí)到的泛型簡(jiǎn)介,但是并沒有很清楚的介紹出泛型的功能作用是什么?
也就是,我們能用泛型來做些什么東西?
那么,來介紹一下泛型的一個(gè)具體的功能。
當(dāng)我們需要對(duì)int類型的變量進(jìn)行處理時(shí),我們寫一個(gè)處理int類型的方法或者類,這是很正常的現(xiàn)象,也是低級(jí)程序猿都會(huì)做的事情,
但是對(duì)于程序猿中的老司機(jī)就不會(huì)這樣去考慮了,他會(huì)考慮,以后會(huì)不會(huì)對(duì)float類型,string類型,或者自定義類型的變量做相同的處理操作?這樣的話,只是單純的去寫一個(gè)int類型的處理函數(shù)或者類,對(duì)以后的可擴(kuò)展性幾乎為0,而且還跟小白程序猿寫一樣的東西,太lowB了,要寫就要寫一些高深的,讓人看不懂的,這才彰顯老司機(jī)的身份。那么我能不能寫一個(gè)通用類型的處理函數(shù)或者類?
老司機(jī)果然就是老司機(jī),遠(yuǎn)遠(yuǎn)不是小白可以比擬的?。。?/p>
但是有人可能會(huì)想到,如果要做一個(gè)通用的類型,那么在C#中所有的類型都是繼承自O(shè)bject類型,寫一個(gè)Object類型的處理方法或者類不就好了?
的確,這是一個(gè)解決方法,看起來也很完美。
但是,但是,但是,不要忘記:裝箱與拆箱(裝箱:將類型轉(zhuǎn)換成object類型,拆箱:將object類型轉(zhuǎn)換成需要的類型)。
當(dāng)你需要處理大量的值類型數(shù)據(jù)的時(shí)候,頻繁的進(jìn)行裝箱與拆箱,那就是傻逼的行為了,請(qǐng)?jiān)徫矣昧松当七@個(gè)詞,但是我控制不住自己??!
雖然處理大量的引用類型不需要裝箱與拆箱,但是頻繁的進(jìn)行強(qiáng)轉(zhuǎn)也是一個(gè)負(fù)擔(dān)。
但是,如果老司機(jī)要這樣去寫一個(gè)通用類型的處理方法或者類,他就會(huì)用到泛型?。?!
泛型用一個(gè)通過的數(shù)據(jù)類型T來代替object,在類實(shí)例化時(shí)指定T的類型,運(yùn)行時(shí)(Runtime)自動(dòng)編譯為本地代碼,運(yùn)行效率和代碼質(zhì)量都有很大提高,并且保證數(shù)據(jù)類型安全。
其實(shí),也就是說,我們先用一個(gè)“身份模糊”的類型來搭建模板,然后在遇到具體事件的時(shí)候,將這個(gè)模板的類型身份根據(jù)具體事件而確定下來,這就是泛型的方便之處。
因?yàn)楸酒涗浀氖欠盒皖?,所以,來一個(gè)泛型類的代碼:
比如,我們需要一個(gè)處理數(shù)據(jù)存儲(chǔ)的類,可能會(huì)存儲(chǔ)int類型,float類型等。
C#中數(shù)據(jù)類型有兩大類:引用類型和值類型。值類型一般是非nullable的值類型,如int, long, struct等,在泛型的約束中,我們也可以大范圍地限制類型T必須是引用類型或必須是值類型,分別對(duì)應(yīng)的關(guān)鍵字是class和struct:
public class DataSave<T> where T:struct
{
private T data;
private T des;
public DataSave(T data){
this.data=data;
}
public T _Des{
set{des=value;}
get{return des;}
}
public void SaveData(List<T> list,T data){
list.add(data);
}
}
然后,我們就可以這樣用了。
static void Main(string args[])
{
List<int> intDataList = new List<int>();
DataSave<int> intData = new DataSave<int>(100);
intData.SaveData(intDataList,intData.data);
}
當(dāng)然,你可以把int類型變成float,但是在實(shí)例化時(shí),要注意格式問題,別忘記尖括號(hào)。
那么從泛型類到一個(gè)具體的類型,中間是如何轉(zhuǎn)換的呢?
其實(shí),C#在編譯泛型類時(shí),是先會(huì)生成中間代碼IL,通用類型T只是一個(gè)占位符,在進(jìn)行指定具體類型時(shí),將由用戶指定的具體類型代替通用類型T并由即時(shí)編譯器(JIT)生成本地代碼,此時(shí)這個(gè)本地代碼中的類型已經(jīng)是用戶指定的具體類型了,后面的過程其實(shí)就是針對(duì)這個(gè)具體類型進(jìn)行操作了,就跟我們的通用類型模板已經(jīng)沒關(guān)系了。
也就是說:DataSave<int> 與 DataSave<float> 是兩個(gè)完全沒有任何關(guān)系的類型。
關(guān)于,針對(duì)通用類型T的約束,就是上一篇中記錄的那樣,使用where關(guān)鍵字進(jìn)行約束,約束的方式是指定T的祖先,即繼承的接口或類。因?yàn)镃#的單根繼承性,所以約束可以有多個(gè)接口,但最多只能有一個(gè)類,并且類必須在接口之前。
但是,通用類型是無法用運(yùn)算符進(jìn)行大小比較的,那么這怎么解決呢?
通過繼承IComparable接口來實(shí)現(xiàn)。
當(dāng)然,你也可以定義多個(gè)類型參數(shù)和約束,比如這樣:
public class Base<T,U,V> where T : struct
where U : new()
where V : class
{ }
在編寫我們自己的泛型類型的時(shí)候,可以通過繼承接口來實(shí)現(xiàn)一些我們知道的需要的方法。
泛型類是一個(gè)很方便的技術(shù),極大的方便了代碼重用,以及如何優(yōu)雅的解決一些復(fù)用代碼的問題。
泛型類型記錄到這里,下面會(huì)記錄一些泛型類型中的一些成員。