[英]Noobie Delegate Fundamentals C#
我不認為我理解委托方法的要點。 我見過的所有例子都是這樣的:
class DelegateClass
{
private List<string> ListString = new List<string>;
delegate void DoSomethingToStringsDelegate(string s);
public base()
{
ListString.Add("string"); ....
}
void ProcessStrings(DoSomethingToStringsDelegate dstsd)
{
foreach(string s in ListString)
dstsd(s);
}
}
class AClass
{
...
void UseDelegateMethod(...)
{
DelegateClass ds = new DelegateClass();
ds.ProcessStrings(new DoSomethingToStringsDelegate(PrintStrings);
}
void PrintStrings(string s)
{
System.out.Write(s);
}
}
我不明白為什么只需要實現一個getListStrings()並自己遍歷字符串,執行你需要做的事情,就像它是一個委托一樣。
foreach( string s in ds.ggetListStrings() )
System.out.Write(s);
私人成員的理由沒有意義,因為我可以這樣做:
global List<Strings> myListStrings = new List<Strings>();
ds.ProcessStrings(new DoSomethingToStringsDelegate(GetStrings);
void GetStrings(string s)
{
myListStrings.Add(s);
}
...現在我有相同的列表,因為getListStrings()會做....
有人可以解釋一下嗎? 非常感謝!
delegate
很有用,因為它實際上充當占用string
,用於將string
作為參數並返回void
任何方法。
如果您熟悉C,它類似於函數指針的工作方式。 在它的位置,您可以傳遞任何匹配簽名和返回類型的方法。
例如,假設我想實現一個對一組對象進行排序的方法。 除了對象列表,我還可以傳遞一個委托,指示如何完成排序。 由於任何匹配委托的方法都可以傳遞,我可以在不同的方法之間動態切換,如果我想要減少或增加排序:
delegate int comparisonDelegate(int p1, int p2);
void SortArray(int[] array, comparisonDelegate cmp)
{
// determine order according to cmp
}
int CompareDecreasing(int p1, int p2)
{
if(p1 > p2) return -1;
if(p1 < p2) return 1;
return 0;
}
int CompareIncreasing(int p1, int p2)
{
if(p1 > p2) return 1;
if(p1 < p2) return -1;
return 0;
}
現在我可以將SortArray
稱為:
SortArray(array, new comparisonDelegate(compareDecreasing));
SortArray(array, new comparisonDelegate(compareIncreasing));
我不明白為什么只需要實現一個getListStrings()並自己遍歷字符串,執行你需要做的事情,就像它是一個委托一樣。
這里的目標是創建一個可以對集合起作用的函數,但是可以進行任何操作。
通過示例更容易理解 - 要查看有用的方法和原因的一個很好的示例,請查看LINQ to Objects。
假設您要查看有多少字符串大於4個字符 - Enumerable.Count方法有一個帶有委托的重載 - 可以使用的Func<T,bool>
謂詞。 這允許您指定任何操作並計算元素,即:
List<string> listOfStrings = GetListOfStrings();
int countOfStringsGreaterThanFourChars = listOfStrings.Count(s => s.Length > 4);
在這里,我們傳遞一個委托(通過lambda表達式創建),它給出了我們的標准。 通過使用帶有委托的Count
方法,它適用於任何標准,因此我們不必在每次需要不同條件時重新實現它。
假設我們想看看有多少字符串以“E”開頭,我們可以使用:
int countOfStringsStartingWithE = listOfStrings.Count(s => s.StartsWith("E"));
同樣,我們只需要編寫與我們特定需求相關的代碼,而不是復制遍歷我們的集合並計算項目所需的所有樣板代碼......
在插圖中使用委托可以更改方法的實現。
更好的例子是Comparer方法。 我不會進入IComparer
接口,但足以說明,使用委托,您可以通過將委托傳遞給比較函數來修改排序方法的行為。
http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx
首先,它允許您使用相同的方法簽名注入不同的行為。 在一種情況下,您可能只想添加到列表中。 在另一種情況下,您可能希望添加到列表並寫入日志文件,或者您可能想要在DoSomethingToStringsDelegate
執行的任何其他操作。
從事件的角度來考慮它。 假設您有一個對項目列表進行一些處理的類,並且對於每個項目,消費您的類的人可能希望被通知項目已被處理(可能更新進度條,或更新系統的其他部分) , 隨你)。 讓我們把代表放在一邊,讓我們看看如何使用接口實現這一點:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
}
}
private void ProcessItem(string item){}
}
現在說有人正在消耗這個類:
var mc = new MyClassThatDoesSomething();
mc.ProcessList(); //how do I know when each one has been processed?
所以解決這個問題,讓我們創建一個接口:
public interface IItemProcessed
{
void ItemProcessed(string item);
}
我們現在可以重構我們原來的類:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
if(this.Listener != null)
{
this.Listener.ItemProcessed(item);
}
}
}
private void ProcessItem(string item){}
public IItemProcessed Listener {get;set;}
}
而你班上的消費者現在可以這樣做:
public class ProcessListener : IItemProcessed
{
public void ItemProcessed(string item)
{
Console.WriteLine(item);
//update progress bar, whatever
}
}
var mc = new MyClassThatDoesSomething();
mc.Listener = new ProcessListener();
mc.ProcessList();
既然您已了解這一點,您可以將委托視為迷你接口,然后您可以將原始類更改為:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
if(this.Callback != null)
{
this.Callback(item);
}
}
}
private void ProcessItem(string item){}
public Action<string> Callback {get;set;}
}
和消費者:
var mc = new MyClassThatDoesSomething();
mc.Listener = s =>
{
Console.WriteLine(s);
//update progress bar, whatever
}
mc.ProcessList();
總而言之,您可以將委托視為向外部人員提供一個簡單的“鈎子”到您的代碼中的方式,以便讓它們提供小塊邏輯(想想Linq並過濾集合)或者像我已經演示過的回調/事件以上。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.