← Назад к вопросам

Какой тип данных у делегата?

2.2 Middle🔥 91 комментариев
#ООП и паттерны проектирования#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Тип данных делегата в C#

В C# делегат сам по себе является типом данных - это специальный тип .NET, который представляет собой безопасный объектно-ориентированный указатель на метод. Технически делегат - это ссылочный тип (reference type), который наследуется от класса System.MulticastDelegate, который в свою очередь наследуется от System.Delegate.

Классификация типа делегата

Делегат классифицируется как:

  1. Ссылочный тип (Reference Type) - как и все классы в C#
  2. Тип-обертка для методов - инкапсулирует метод с определенной сигнатурой
  3. Тип, безопасный к типам (type-safe) - обеспечивает проверку типов во время компиляции

Пример объявления и использования делегата

// Объявление типа делегата
public delegate int MathOperation(int a, int b);

class Program
{
    // Методы, совместимые с делегатом
    static int Add(int x, int y) => x + y;
    static int Multiply(int x, int y) => x * y;
    
    static void Main()
    {
        // Создание экземпляра делегата
        MathOperation operation = new MathOperation(Add);
        
        // Вызов через делегат
        int result = operation(5, 3); // result = 8
        
        // Переназначение делегата
        operation = Multiply;
        result = operation(5, 3); // result = 15
        
        // Мультикаст-делегат (составной делегат)
        operation += Add;
        result = operation(5, 3); // Будет вызван только последний метод (Add)
    }
}

Внутренняя структура делегата

Делегат содержит три важных поля:

  • Target - ссылка на объект, для которого вызывается метод (null для статических методов)
  • Method - указатель на метод
  • InvocationList - список методов для мультикаст-делегатов
// Пример исследования свойств делегата
MathOperation op = Add;
Console.WriteLine($"Method: {op.Method.Name}");
Console.WriteLine($"Target: {op.Target}"); // null для статического метода
Console.WriteLine($"Type: {op.GetType().FullName}");

Особенности типа делегата

  1. Безопасность типов - делегат проверяет соответствие сигнатуры метода:
// Это вызовет ошибку компиляции - несовпадение сигнатур
// delegate int MyDelegate(int a, int b);
// void MyMethod(string s) { }
// MyDelegate d = MyMethod; // ОШИБКА!
  1. Возможность создания мультикаст-делегатов:
public delegate void Logger(string message);

Logger log = ConsoleLogger;
log += FileLogger;
log += DatabaseLogger;

// При вызове будут выполнены все три метода
log("Сообщение для логов");
  1. Поддержка анонимных методов и лямбда-выражений:
MathOperation squareSum = (a, b) => (a * a) + (b * b);
int result = squareSum(2, 3); // result = 13

Встроенные обобщенные делегаты

.NET предоставляет готовые обобщенные типы делегатов:

// Func<T> - делегат с возвращаемым значением
Func<int, int, int> addFunc = (x, y) => x + y;

// Action<T> - делегат без возвращаемого значения (void)
Action<string> printAction = message => Console.WriteLine(message);

// Predicate<T> - делегат, возвращающий bool
Predicate<int> isEven = num => num % 2 == 0;

Заключение

Делегат в C# - это полноценный ссылочный тип данных, который предоставляет механизм для реализации обратных вызовов (callbacks), событийной модели и функционального программирования. Он сочетает в себе безопасность типов, объектно-ориентированный дизайн и гибкость, позволяя передавать методы как объекты, хранить их в переменных и структурах данных, что делает его фундаментальным строительным блоком для многих паттернов проектирования в .NET, включая наблюдатель (Observer), стратегия (Strategy) и команда (Command).