.net泛型通用函數的特殊問題的解決方案

來源:互聯網
上載者:User

  自從2.0版本的net framework推出之後泛型(Generic)得到了廣泛好評。它不必像object類型一樣效能上因為“拆箱”或者“裝箱”得到損失,同時在編譯文法檢測階段就可以即時檢測出傳入或者傳出的類型是否符合特定條件。

  但“金無赤足,人無完人”——在我們享受這些幸福編程的同時,泛型自身類型的不確定也帶來了一個顯著的問題——無法進行運算子多載。譬如現在我要寫一個函數(一個通用的選擇排序演算法,使用泛型T),該怎麼辦呢?如果你簡單使用這樣的代碼(C#如下):

複製代碼 代碼如下://從小到大,改進型選擇排序演算法

public static void Sort<T>(T[] array)
{
bool flag = false; //標記是否已經排序

for(int i=0;i<array.Length-1;++i)
{
flag = false; //每次假定都已經排序,無須再排序

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; //已經排序
}
}
if(!flag)
{
break;
}
}
}

  編譯之後很快發現提示“運算子‘>'無法作用於T”一類的提示。

  為什麼呢?我們知道,凡是可以進行大於、小於比較的類型肯定都定義了運算子多載。一般類必須為此定義方可進行比較,不然大於符號或者小於符號(或者其它運算子)無法知道如何比較而發生錯誤。那麼泛型因為事先都不知道什麼類型?編譯器檢查器自然無法推斷你運行時動態傳入的這個類型一定保證是實現了運算子多載,嚴格語法檢查情況下就自然報錯。

  怎麼辦呢?強制規定泛型T必須實現比較子(強制T必須實現IComparable,或者類似介面)。

複製代碼 代碼如下:public static void Sort<T>(T[] array)where T:IComparable
{
bool flag = false; //標記是否已經排序

for(int i=0;i<array.Length-1;++i)
{
flag = false; //每次假定都已經排序,無須再排序

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; //已經排序
}
}
if(!flag)
{
break;
}
}
}

  一旦對泛型進行約束,那麼泛型必然是實現該介面的類,必然擁有此方法(Compare方法返回結果int類型,如果大於0表示前面一個數字大於後面一個)。

  當然,微軟類庫中有一個Comparer靜態類,已經實現了此介面可以直接進行比較(http://msdn.microsoft.com/zh-cn/library/system.collections.comparer.comparer.aspx),因此我們也可以選擇直接使用這個靜態類中的Compare方法得到結果。

  【例2】實現一個通用的“+”——即如果傳入的字串,則自動按照字串進行字元拼接;如果傳入的是其它基本類型(int,double等),則返回相加結果。

  微軟沒有為“+”預定義介面,因此無法直接使用介面的方式來做(當然你自己強制定義一個,也可以如法炮製)。我們現在換一個方法——使用運算式樹狀架構(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();
}

  動態判斷T是string還是其它基本類型,然後調用不同的方法組合成為運算式樹狀架構,動態編譯成為一個Func運算式,返回結果即可。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.