ожидает функцию, которая принимает IEnumerable и Exception и возвращает void.
void SendExceptionToCustomers(IEnumerable<Customer> customers, Exception ex) {
foreach(var customer in customers)
customer.SendMessage(ex.Message);
}
GetCustomers(SendExceptionToCustomers);
Кстати, GetCustomers кажется ужасным названием для этой функции - она требует действия, поэтому она больше похожа на DoSomethingToCustomers
РЕДАКТИРОВАТЬ в ответ на комментарий
Хорошо. Имеет смысл, так зачем теперь беспокоиться о наличии функции GetCustomer? Разве я не могу сделать то же самое с вашей функцией, если я просто переименую ее в GetCustomer?
Что здесь происходит, вызывающий может указать какое-то действие. Предположим, что GetCustomers реализован так:
public void GetCustomers(Action<Enumerable<Customer>, Exception> handleError) {
Customer[] customerlist = GetCustomersFromDatabase();
try {
foreach(var c in customerList)
c.ProcessSomething()
} catch (Exception e) {
handleError(customerList, e);
}
}
тогда вы можете вызвать Getcustomers откуда-нибудь из программы командной строки и передать ее
GetCustomers((list, exception) => {
Console.WriteLine("Encountered error processing the following customers");
foreach(var customer in list) Console.WriteLine(customer.Name);
Console.WriteLine(exception.Message);
});
в то время как вы можете вызвать GetCustomers, например, из удаленного приложения, и передать его
Getcustomers((list, exception) => {
// code that emails me the exception message and customer list
})
Кроме того, комментарий Слака предлагает еще одну причину для параметра делегата - GetCustomers действительно получает клиентов, но асинхронно. Всякий раз, когда это делается для извлечения клиентов, он вызывает функцию, которую вы ей даете, либо со списком клиентов, либо с исключением, если произошло исключение.