Predicate 泛型委派
表示定義一組條件並確定指定對象是否符合這些條件的方法。此委託由 Array 和 List 類的幾種方法使用,用於在集合中搜尋元素。
看看下面它的定義:
// Summary:
// Represents the method that defines a set of criteria and determines whether
// the specified object meets those criteria.
//
// Parameters:
// obj:
// The object to compare against the criteria defined within the method represented
// by this delegate.
//
// Type parameters:
// T:
// The type of the object to compare.
//
// Returns:
// true if obj meets the criteria defined within the method represented by this
// delegate; otherwise, false.
public delegate bool Predicate<T>(T obj);
型別參數介紹:
T: 要比較的對象的類型。
obj: 要按照由此委託表示的方法中定義的條件進行比較的對象。
傳回值:如果 obj 符合由此委託表示的方法中定義的條件,則為 true;否則為 false。
看下面代碼:
public class GenericDelegateDemo
{
List<String> listString = new List<String>()
{
"One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"
};
String[] arrayString = new String[]
{
"One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"
};
public String[] GetFirstStringFromArray()
{
return Array.FindAll(arrayString, (c) => { return c.Length <= 3; });
}
public List<String> GetFirstStringFromList()
{
return listString.FindAll((c) => { return c.Length <= 3; });
}
public String[] GetFirstStringFromArray_1()
{
return Array.FindAll(arrayString, GetString);
}
public List<String> GetFirstStringFromList_1()
{
return listString.FindAll(GetString);
}
private bool GetString(String str)
{
if (str.Length <= 3)
return true;
else
return false;
}
}
(1)首先,上面以 數組和泛型List 兩個集合作為示範對象,並構建集合。
(2)接著,兩者同時使用各自 所有的 FindALL方法,參見如下定義:
Array : public T[] FindAll<T>(T[] array, Predicate<T> match);
List:public List<T> FindAll(Predicate<T> match);
注意的是,兩處的FindAll 均採用了Predicate (泛型委派)作為參數的類型。
(3)接著,使用兩者方式展現 對Predicate 的使用:
第一種: (c) => { return c.Length <= 3; };
第二種: GetString(String str)。
這兩者在文法上明顯不同,但是實際是做相同的事情,第一種是使用Lambda運算式構建的語句,關於Lambda這裡不做詳述,請參見筆者C#3.0特性相關文章。
補充的是你也可以這樣寫,
delegate(String c){return c.Length<=3;} 作為 Predicate定義的參數
完整代碼:
XX.FindAll(delegate(String c) { return c.Length <= 3; });
這應該稱為匿名代理了。
其他使用到Predicate 有
Array.Find , Array.FindAll , Array.Exists , Array.FindLast , Array.FindIndex .....
List<T>.Find , List<T>.FindAll , List<T>.Exists , List<T>.FindLast , List<T>.FindIndex .....
延伸:
除了上面提到的外,你完全可以使用Predicate 定義新的方法,來加強自己代碼。
public class GenericDelegateDemo
{
List<String> listString = new List<String>()
{
"One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"
};
public String GetStringList(Predicate<String> p)
{
foreach(string item in listString)
{
if (p(item))
return item;
}
return null;
}
public bool ExistString()
{
string str = GetStringList((c) => { return c.Length <= 3 && c.Contains('S'); });
if (str == null)
return false;
else
return true;
}
}
同樣解決了上面的問題,這裡羅嗦了只是為說明Predicate的用法而已。
對於Predicate的應用當然這不是什麼新鮮事情,今天細細思味一番,覺得C# 真是一門優雅的語言。
以供初學者參考。
筆者本想對以下幾種泛型委派一一做些介紹和總結的,在理解Predicate的過程中,發現只要理解了泛型、委託和匿名代理,
當然你曉得Lambda運算式更好,就完全可以在適當的時候靈活應用他們了。也就是說,只是定義不同的delegate而已,
一是 你可以自己定義這樣的delegate,再行使用;
二是 你需要知道象Predicate、Func、Action這樣的已有好的delegate是如何定義的。或者使用的時候適當查閱下MSDN即可。
如:
Func():封裝一個不具有參數但卻返回 TResult 參數指定的類型值的方法。
Func(T1, T2, TResult):封裝一個具有兩個參數並返回 TResult 參數指定的類型值的方法,沒有T2就是封裝一個具有參數並....。
Action() Action(T1) Action(T2) : 封裝一個方法,該方法指定數量的參數(如()無參數,(T1)一個參數,以此類推)並且不傳回值。這個和Func有相似處,但無傳回值而已。
提醒大家的注意的是:
x=>x+x;
與
X=> {return x+x;} 是等價的。