簡體   English   中英

Noobie代表基礎知識C#

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM