Думайте об этом с точки зрения событий. Скажем, у вас есть класс, который выполняет некоторую обработку списка элементов, и для каждого элемента кто-то, потребляющий ваш класс, может захотеть получить уведомление о том, что элемент обработан (возможно, обновить индикатор выполнения или обновить какую-то другую часть системы). , без разницы). Давайте отложим делегатов на секунду и посмотрим, как мы можем реализовать это с помощью интерфейсов:
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 и фильтрацию коллекции) или для обратных вызовов / событий, подобных I продемонстрировал выше.