今天看到首頁有個委托的文章,但大都寫的太專業,而且沒有實用的例子場景。正好昨天做了一個有關委托的功能,所以也來湊個熱鬧,用白話掰掰
一、委托是什么
我們都知道數據類型,簡單點的如,想給一個變量賦值整數,那就要定義一個 int類型的變量
int var=5;
想給一個變量賦值字符串那就定義一個string類型的變量
string var ="test";
復雜點的就是自己定義一個類,然后就可以定義類變量
MyClass myClass= new MyClass();
現在我們有如下一個方法,怎樣把這個方法可以賦值給一個變量呢?
public string GetMessage(string messageType) { string ret = ""; switch (messageType) { case "error": ret = "錯誤消息"; break; case "warning": ret = "警告消息"; break; default: ret = "未知消息"; break; } return ret; }
這個就要委托來登場了。先看實現
delegate string MessageDelegate(string messageType); public void Test() { MessageDelegate myMessage = GetMessage; string ret = myMessage("error"); }
定義一個類大家都會 ,用 class 關鍵字來定義一個類MyClass
class MyClass { }
同理,用 delegate 關鍵字來定義一個委托 MessageDelegate。
一定要有這個一個概念,我們用 delegate 關鍵字定義的委托(MessageDelegate)是一個數據類型。
int 類型的變量用來賦值整數的,string類型的變量用來賦值字符串的,而委托類型的變量是用來賦值函數的。
當然因為每個函數的參數不同,返回的數據不同,所以在定義委托的時候也就指明了這個委托類型的變量可接受的函數。
delegate string MessageDelegate(string messageType);
如上面定義的MessageDeletegate委托數據類型,用MessageDeletegate定義的變量(myMessage)只能接受 有一個string類型的參數並且有一個sting返回值的函數(GetMessage)
MessageDelegate myMessage = GetMessage;
delegate void MyDelete(int i);
上面定義的這個MyDelete委托類型對應的函數是有一個int類型的參數,並且沒有返回值。
二、委托的使用
在.net中委托基本隨處可見,最常用的就是Action、Func和Predicate,它們分別有很多重載,自己可以看看。
public delegate void Action(); public delegate TResult Func<out TResult>(); public delegate bool Predicate<in T>(T obj);
現在有這么一個功能:
現在有一個int類型的集合,把所有的偶數乘以2,輸出到一個新集合中。
測試數據:
List<int> myList = new List<int>(); for (int i = 0; i < 10; i++) { myList.Add(i); }
普通方法實現:
List<int> retList = new List<int>(); for (int i = 0; i < myList.Count; i++) { if (myList[i] % 2 == 0) { retList.Add(myList[i] * 2); } }
用委托方法實現:
List<int> retList = new List<int>(); myList.ForEach((data) => { if (data % 2 == 0) { retList.Add(data * 2); } });
當然這個ForEach是.net提供的擴展方法,再加上lambda表達式實現。
這個還不足以說明委托的好處。
如果我們再把問題放寬點,現在有一個int類型的集合,如果里面的數字滿足某個條件,則執行某個動作。
public void MyOperation(List<int> myList, Func<int, bool> func, Action<int> action) { for (int i = 0; i < myList.Count; i++) { if (func(myList[i])) { action(myList[i]); } } }
現在在把第一個問題實現下:
MyOperation(myList, (d) => { return d % 2 == 0; }, (d) => { retList.Add(d * 2); });
可以近一步寫成擴展方法,這個有跑題有點遠了。
上面這個例子主要是說明了一點:
委托是一個函數類型的數據類型(對比int是一個整數類型的數據類型),可以把委托當做參數變量來傳遞。
然而因為委托變量的值是函數,這樣就可以把一個函數當做參數傳遞到另外一個函數中。
如上面提到的:
寫一個對集合操作的函數,如果集合里面的某個元素滿足某個條件,則執行某個動作。