自定義Delegate時,我們常常發現Delegate必須全局可見,才能在需要的地方進行使用,而對於私有的delegate對象,在本類中進行使用,這似乎是不方便的。下邊我們來看傳統的Delegate的寫法:
public delegate void MyDelegate(string name);
public class MyBlogBase
{
private MyDelegate mydelegate;
}
必須保證MyDelegate放在類的外邊,才能在其他地方可見,並使用。Action,Func的出現改變了這一局面,這兩個其實說白了就是系統定義好的Delegate,他有很多重載的方法,便於各種應用情況下的調用。他在系統的System命名空間下,因此全局可見。下文就說明Action,Action有多個重載,下文已Action<T>
爲例進行說明
Action<T>
:封裝一個方法,該方法只有一個參數並且不返回值。其中T是可接收的任何類型。使用代碼如下:
public class MyBlogBase
{
public string myName;
Action<string> myAction;
public MyBlogBase()
{
//myAction = delegate(string curName) { myName = curName; };
//myAction = new Action<string>(SetAction);
myAction = curname => { myName = curname; };
}
private void SetAction(string name)
{
myName = name;
}
}
在上例中,給出了3種使用Action的方法,方法一:採用匿名委託,方法二:指定一個實際的方法。方法三:使用Lamda表達式。以上3中用法均可運行。
在實際應用中要比原始的定義Delegate方便,靈活。那麼Func呢?
Func<T in,T Tresult>
:封裝一個具有一個參數並返回 TResult 參數指定的類型值的方法。其實個人感覺,Func和Action的區別很明顯,也很直接。二者都是委託,但Func能返回函數執行結果,而Action返回類型是Void,這個區別很明顯,在具體的項目中,也很容易確定該使用那個。下文就說明具體Func的代碼調用:
public string myName;
Func<string, string> myFunc;
public MyBlogBase()
{
//myFunc = delegate(string curName) { return curName.ToUpper(); };
//myFunc = new Func<string, string>(SetFunc);
myFunc = name => { return name.ToUpper(); };
}
private string SetFunc(string name)
{
return name.ToUpper();
}
public void StartFun(string curName)
{
myName = myFunc(curName)
}
如上3種寫法,都是合適的Func定義,大家可以選擇適合自己的編程模式,其實匿名方法,有個優點,就是可以直接使用當前函數出現的變量,代碼更簡潔,但可能有些人覺得不易讀。
Predicate<T>
:也是一種委託,表示定義一組條件並確定指定對象是否符合這些條件的方法.此方法常在集合的查找中被用到,如:數組,正則拼配的結果集中被用到。使用此方法快捷方便,使用代碼如下:
Predicate<int[]> myPredicate;
int[] myNum = new int[8] { 12, 33, 89, 21, 15, 29, 40, 52 };
public int[] myResult;
public MyBlogBase()
{
myPredicate = delegate(int curNum) { if(curNum % 2 == 0) return true; else return false; };
//myPredicate = n => n % 2 == 0;
}
public void StartPredicate()
{
myResult = Array.FindAll(myNum, myPredicate);
}
上例中說明了Predicate的使用,FindAll方法中,參數2即是一個Predicate,在具體的執行中,每一個數組的元素都會執行指定的方法,如果滿足要求返回true,並會被存放在結果集中,不符合的則被剔除,最終返回的集合,即是結果判斷後想要的集合,此方法應用場景感覺像迭代中的yield。
爲了更好的驗證運行效果,添加Test項目及進行測試,把代碼粘帖出來分享一下:
[TestMethod]
public void TestAction()
{
MyBlogBase blogObj = new MyBlogBase();
blogObj.StartAction("ywg369");
Assert.AreEqual("ywg369", blogObj.myName);
}
[TestMethod]
public void TestFunc()
{
MyBlogBase blogObj = new MyBlogBase();
blogObj.StartFun("ywg369");
Assert.AreEqual("YWG369", blogObj.myName);
}
[TestMethod]
public void TestPredicate()
{
MyBlogBase blogObj = new MyBlogBase();
blogObj.StartPredicate();
Assert.AreEqual(3, blogObj.myResult.Length);
}
經過驗證,運行良好,各個方法都按照期望的結果運行成功。通過此處對Delegate,Action,Func,Predicate的使用有個大致的瞭解,在具體的應用中根據實際情況進行調用。
總結:
1.Func,Action,Predicate都是微軟提供的定義好的委託類型,他們都位於System命名空間下,使用這幾個委託可以簡化代碼的編寫,比自定義委託使用起來更加方便;
2.Func委託具有返回值,並且可以有0到16個參數;
3.Action委託不具有返回值,可以有0到16個參數;
4.Predicate表示定義一組條件並確定指定對象是否符合這些條件的方法,他具有一個bool類型的返回值,符合由此委託表示的方法中定義的條件,則爲true,否則爲false;