Хотя в примере наш делегат принимал адрес на один метод, в действительности он может указывать сразу на несколько методов. Кроме того, при необходимости мы можем удалить ссылки на адреса определенных методов, чтобы они не вызывались при вызове делегата. Итак, изменим в классе Account метод RegisterHandler и добавим новый метод UnregisterHandler, который будет удалять методы из списка методов делегата:
public delegate void AccountHandler(string message);
public class Account
{
int sum;
AccountHandler? taken;
public Account(int sum) => this.sum = sum;
// Регистрируем делегат
public void RegisterHandler(AccountHandler del)
{
taken += del;
}
// Отмена регистрации делегата
public void UnregisterHandler(AccountHandler del)
{
taken -= del; // удаляем делегат
}
public void Add(int sum) => this.sum += sum;
public void Take(int sum)
{
if (this.sum >= sum)
{
this.sum -= sum;
taken?.Invoke($"Со счета списано {sum} у.е.");
}
else
taken?.Invoke($"Недостаточно средств. Баланс: {this.sum} у.е.");
}
}
В первом методе объединяет делегаты taken и del в один, который потом присваивается переменной taken. Во втором методе из переменной taken удаляется делегат del.
Применим новые методы:
Account account = new Account(200);
// Добавляем в делегат ссылку на методы
account.RegisterHandler(PrintSimpleMessage);
account.RegisterHandler(PrintColorMessage);
// Два раза подряд пытаемся снять деньги
account.Take(100);
account.Take(150);
// Удаляем делегат
account.UnregisterHandler(PrintColorMessage);
// снова пытаемся снять деньги
account.Take(50);
void PrintSimpleMessage(string message) => Console.WriteLine(message);
void PrintColorMessage(string message)
{
// Устанавливаем красный цвет символов
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message);
// Сбрасываем настройки цвета
Console.ResetColor();
}
В целях тестирования мы создали еще один метод - PrintColorMessage, который выводит то же самое сообщение только красным цветом. Ссылка на этот метод также передается в метод RegisterHandler, и таким образом ее получит переменная taken.
В строке account.UnregisterHandler(PrintColorMessage); этот метод удаляется из списка вызовов делегата, поэтому этот метод больше не будет срабатывать. Консольный вывод будет иметь следующую форму:
Со счета списано 100 у.е.
Со счета списано 100 у.е.
Недостаточно средств. Баланс: 100 у.е.
Недостаточно средств. Баланс: 100 у.е.
Со счета списано 50 у.е.