.net泛型通用函數(shù)的特殊問題的解決方法
自從2.0版本的net framework推出之后泛型(Generic)得到了廣泛好評(píng)。它不必像object類型一樣性能上因?yàn)椤安鹣洹被蛘摺把b箱”得到損失,同時(shí)在編譯語法檢測(cè)階段就可以實(shí)時(shí)檢測(cè)出傳入或者傳出的類型是否符合特定條件。
但“金無赤足,人無完人”——在我們享受這些幸福編程的同時(shí),泛型自身類型的不確定也帶來了一個(gè)顯著的問題——無法進(jìn)行運(yùn)算符重載。譬如現(xiàn)在我要寫一個(gè)函數(shù)(一個(gè)通用的選擇排序算法,使用泛型T),該怎么辦呢?如果你簡(jiǎn)單使用這樣的代碼(C#如下):
//從小到大,改進(jìn)型選擇排序算法
public static void Sort<T>(T[] array)
{
bool flag = false; //標(biāo)記是否已經(jīng)排序
for(int i=0;i<array.Length-1;++i)
{
flag = false; //每次假定都已經(jīng)排序,無須再排序
for(int j=i+1;i<array.Length;++j)
{
if(array[i]>array[j])
{
int temp = array[i];
array[i]=array[j];
array[j]=templ
flag = true; //已經(jīng)排序
}
}
if(!flag)
{
break;
}
}
}
編譯之后很快發(fā)現(xiàn)提示“運(yùn)算符‘>'無法作用于T”一類的提示。
為什么呢?我們知道,凡是可以進(jìn)行大于、小于比較的類型肯定都定義了運(yùn)算符重載。一般類必須為此定義方可進(jìn)行比較,不然大于號(hào)或者小于號(hào)(或者其它運(yùn)算符)無法知道如何比較而發(fā)生錯(cuò)誤。那么泛型因?yàn)槭孪榷疾恢朗裁搭愋??編譯器檢查器自然無法推斷你運(yùn)行時(shí)動(dòng)態(tài)傳入的這個(gè)類型一定保證是實(shí)現(xiàn)了運(yùn)算符重載,嚴(yán)格語法檢查情況下就自然報(bào)錯(cuò)。
怎么辦呢?強(qiáng)制規(guī)定泛型T必須實(shí)現(xiàn)比較器(強(qiáng)制T必須實(shí)現(xiàn)IComparable,或者類似接口)。
public static void Sort<T>(T[] array)where T:IComparable
{
bool flag = false; //標(biāo)記是否已經(jīng)排序
for(int i=0;i<array.Length-1;++i)
{
flag = false; //每次假定都已經(jīng)排序,無須再排序
for(int j=i+1;i<array.Length;++j)
{
if(array[i].Compare(array[j])>0)
{
int temp = array[i];
array[i]=array[j];
array[j]=templ
flag = true; //已經(jīng)排序
}
}
if(!flag)
{
break;
}
}
}
一旦對(duì)泛型進(jìn)行約束,那么泛型必然是實(shí)現(xiàn)該接口的類,必然擁有此方法(Compare方法返回結(jié)果int類型,如果大于0表示前面一個(gè)數(shù)字大于后面一個(gè))。
當(dāng)然,微軟類庫(kù)中有一個(gè)Comparer靜態(tài)類,已經(jīng)實(shí)現(xiàn)了此接口可以直接進(jìn)行比較(http://msdn.microsoft.com/zh-cn/library/system.collections.comparer.comparer.aspx),因此我們也可以選擇直接使用這個(gè)靜態(tài)類中的Compare方法得到結(jié)果。
【例2】實(shí)現(xiàn)一個(gè)通用的“+”——即如果傳入的字符串,則自動(dòng)按照字符串進(jìn)行字符拼接;如果傳入的是其它基本類型(int,double等),則返回相加結(jié)果。
微軟沒有為“+”預(yù)定義接口,因此無法直接使用接口的方式來做(當(dāng)然你自己強(qiáng)制定義一個(gè),也可以如法炮制)。我們現(xiàn)在換一個(gè)方法——使用表達(dá)式樹(C#代碼如下):
public static T Add<T>(T a, T b)
{
Expression left = Expression.Constant(a);
Expression right = Expression.Constant(b);
Type t = typeof(T);
Expression value;
if (t == typeof(string))
{
value = Expression.Constant(a.ToString()+b.ToString());
}
else
{
value = Expression.Add(left, right);
}
Expression<Func<T>> addExp = Expression.Lambda<Func<T>>(value);
Func<T> addFunc = addExp.Compile();
return addFunc();
}
動(dòng)態(tài)判斷T是string還是其它基本類型,然后調(diào)用不同的方法組合成為表達(dá)式樹,動(dòng)態(tài)編譯成為一個(gè)Func表達(dá)式,返回結(jié)果即可。
相關(guān)文章
Asp.net中DataTable導(dǎo)出到Excel的方法介紹
本篇文章介紹了,Asp.net中DataTable導(dǎo)出到Excel的方法。需要的朋友參考下2013-05-05Windows Server 2012 R2 或 2016無法安裝.Net 3.5.1
這篇文章主要為大家詳細(xì)介紹了Windows Server 2012 R2 或 2016 無法安裝 .Net 3.5.1,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02對(duì)Entity?Framework?Core進(jìn)行單元測(cè)試
這篇文章介紹了對(duì)Entity?Framework?Core進(jìn)行單元測(cè)試的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03asp.net線程批量導(dǎo)入數(shù)據(jù)時(shí)通過ajax獲取執(zhí)行狀態(tài)
asp.net線程批量導(dǎo)入數(shù)據(jù)是大家日常工作中常遇到的一個(gè)要求,但批量添加時(shí)間一般較長(zhǎng),如果能返回執(zhí)行的狀態(tài)就好,那么下面這篇文章主要給大家介紹了asp.net線程批量導(dǎo)入數(shù)據(jù)時(shí)通過ajax獲取執(zhí)行狀態(tài)的方法,有需要的朋友可以參考下。2016-12-12利用AJAX與數(shù)據(jù)島實(shí)現(xiàn)無刷新綁定
利用AJAX與數(shù)據(jù)島實(shí)現(xiàn)無刷新綁定...2007-03-03asp.net動(dòng)態(tài)產(chǎn)生checkbox(數(shù)據(jù)源為DB或內(nèi)存集合)
動(dòng)態(tài)產(chǎn)生一組checkbox(數(shù)據(jù)源為DB或內(nèi)存集合)且post提交時(shí)后臺(tái)能及時(shí)獲取等等,打算使用repeater+input(checkbox)+input(hidden)來實(shí)現(xiàn)2013-10-10.NET性能調(diào)優(yōu)之一:ANTS Performance Profiler的使用介紹
本系列文章主要會(huì)介紹一些.NET性能調(diào)優(yōu)的工具、Web性能優(yōu)化的規(guī)則(如YSlow)及方法等等內(nèi)容。成文前最不希望看到的就是園子里不間斷的“哪個(gè)語言好,哪個(gè)語言性能高”的爭(zhēng)論,不多說,真正的明白人都應(yīng)該知道這樣的爭(zhēng)論有沒有意義,希望我們能從實(shí)際性能優(yōu)化的角度去討論問題2013-01-01asp.net core配合vue實(shí)現(xiàn)后端驗(yàn)證碼邏輯
網(wǎng)上的前端驗(yàn)證碼邏輯總感覺不安全,驗(yàn)證碼建議還是使用后端配合驗(yàn)證。本文主要介紹了asp.net core配合vue實(shí)現(xiàn)后端驗(yàn)證碼邏輯,感興趣的可以了解一下2021-06-06使用Visual Studio創(chuàng)建ASP.NET Web API項(xiàng)目
這篇文章介紹了使用Visual Studio創(chuàng)建ASP.NET Web API項(xiàng)目的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03三層+存儲(chǔ)過程實(shí)現(xiàn)分頁(yè)示例代碼
本文為大家介紹下三層+存儲(chǔ)過程分頁(yè)的具體實(shí)現(xiàn),前后臺(tái)及存儲(chǔ)過程代碼如下,感興趣的朋友可以參考下哈2013-06-06