Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Делегаты в C#
Делегат это типобезопасная ссылка на метод. Это позволяет передавать методы как параметры, сохранять их в переменных и вызывать их позже. Делегаты это основа для событий, коллбеков и функционального программирования в C#.
Базовое понимание
Что такое делегат?
Делегат это класс, который может хранить ссылку на метод с определённой сигнатурой.
// Объявляем делегат
public delegate void MyCallback(string message);
// Метод с совместимой сигнатурой
public void PrintMessage(string message) {
Debug.Log(message);
}
// Создаём переменную делегата и присваиваем метод
MyCallback callback = PrintMessage;
// Вызываем делегат
callback("Привет"); // Выведет: Привет
Зачем нужны делегаты?
1. Передача методов как параметров
public delegate void ProcessAction(int value);
public class DataProcessor {
public void ProcessData(int[] data, ProcessAction action) {
foreach (var item in data) {
action(item); // Вызываем переданный метод
}
}
}
// Использование
var processor = new DataProcessor();
int[] numbers = { 1, 2, 3, 4, 5 };
processor.ProcessData(numbers, (x) => Debug.Log("Число: " + x));
processor.ProcessData(numbers, (x) => Debug.Log("Квадрат: " + (x * x)));
2. Асинхронные операции и коллбеки
public delegate void OperationComplete(bool success);
public class NetworkManager {
public void FetchData(string url, OperationComplete onComplete) {
StartCoroutine(FetchDataCoroutine(url, onComplete));
}
private IEnumerator FetchDataCoroutine(string url, OperationComplete onComplete) {
using (var www = new WWW(url)) {
yield return www;
onComplete(www.error == null); // Коллбек когда готово
}
}
}
// Использование
var network = new NetworkManager();
network.FetchData("https://api.example.com", (success) => {
if (success) {
Debug.Log("Данные загружены");
} else {
Debug.Log("Ошибка загрузки");
}
});
Встроенные делегаты
Action — делегат без возвращаемого значения
// Action с параметром
Action<string> printAction = (message) => Debug.Log(message);
printAction("Hello");
// Action с несколькими параметрами
Action<int, int> addAction = (a, b) => Debug.Log(a + b);
addAction(5, 3); // Выведет: 8
// Action без параметров
Action greet = () => Debug.Log("Привет!");
greet();
Func — делегат с возвращаемым значением
// Func<параметры, возвращаемый тип>
Func<int, int, int> multiply = (a, b) => a * b;
int result = multiply(4, 5); // result = 20
Func<string, bool> isLong = (text) => text.Length > 5;
bool check = isLong("Hello World"); // true
События (Events)
События это безопасная обёртка над делегатами. Позволяют подписываться и отписываться.
public class Enemy {
// Делегат для события
public delegate void DeathEventHandler(Enemy enemy);
// Событие на основе делегата
public event DeathEventHandler OnDeath;
public void Die() {
Debug.Log("Enemy died");
OnDeath?.Invoke(this); // Вызываем всех подписчиков
}
}
// Использование
var enemy = new Enemy();
enemy.OnDeath += (deadEnemy) => Debug.Log("Враг повержен!");
enemy.OnDeath += (deadEnemy) => DropLoot();
enemy.Die(); // Выведет обе подписки
// Отписка
enemy.OnDeath -= (deadEnemy) => Debug.Log("Враг повержен!");
Практические примеры
1. Система событий игры
public class GameEvents {
public static event Action<int> OnScoreChanged;
public static event Action<float> OnHealthChanged;
public static event Action OnGameOver;
public static void RaiseScoreChanged(int newScore) {
OnScoreChanged?.Invoke(newScore);
}
public static void RaiseHealthChanged(float health) {
OnHealthChanged?.Invoke(health);
}
public static void RaiseGameOver() {
OnGameOver?.Invoke();
}
}
// Подписка
public class UI : MonoBehaviour {
private void OnEnable() {
GameEvents.OnScoreChanged += UpdateScoreDisplay;
GameEvents.OnHealthChanged += UpdateHealthBar;
}
private void OnDisable() {
GameEvents.OnScoreChanged -= UpdateScoreDisplay;
GameEvents.OnHealthChanged -= UpdateHealthBar;
}
private void UpdateScoreDisplay(int score) {
scoreText.text = "Score: " + score;
}
private void UpdateHealthBar(float health) {
healthBar.value = health;
}
}
2. Система обработки урона
public delegate void DamageHandler(int damage, Vector3 position);
public class Character {
public event DamageHandler OnTakeDamage;
private int health = 100;
public void TakeDamage(int damage, Vector3 position) {
health -= damage;
OnTakeDamage?.Invoke(damage, position);
}
}
public class ParticleEffects : MonoBehaviour {
public void PlayDamageEffect(int damage, Vector3 position) {
Instantiate(damageParticle, position, Quaternion.identity);
}
}
public class AudioManager : MonoBehaviour {
public void PlayDamageSound(int damage, Vector3 position) {
AudioSource.PlayClipAtPoint(damageSound, position);
}
}
// Подключение к событиям
var character = GetComponent<Character>();
character.OnTakeDamage += particles.PlayDamageEffect;
character.OnTakeDamage += audioManager.PlayDamageSound;
3. Функции высокого порядка (Higher-Order Functions)
public class CollectionUtils {
public static List<T> Filter<T>(List<T> items, Func<T, bool> predicate) {
var result = new List<T>();
foreach (var item in items) {
if (predicate(item)) {
result.Add(item);
}
}
return result;
}
public static List<U> Map<T, U>(List<T> items, Func<T, U> transform) {
var result = new List<U>();
foreach (var item in items) {
result.Add(transform(item));
}
return result;
}
}
// Использование
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = CollectionUtils.Filter(numbers, (x) => x % 2 == 0);
var doubled = CollectionUtils.Map(numbers, (x) => x * 2);
Многие делегаты (Multicast Delegates)
public delegate void Callback();
Callback callback = null;
callback += () => Debug.Log("1");
callback += () => Debug.Log("2");
callback += () => Debug.Log("3");
callback?.Invoke();
// Выведет:
// 1
// 2
// 3
Выводы
- Делегат это типобезопасная ссылка на метод
- Action для методов без результата
- Func для методов с результатом
- События это безопасная обёртка над делегатами
- Используй делегаты для архитектуры на основе событий
- Всегда отписывайся от событий в OnDisable() чтобы избежать утечек памяти
- Делегаты это основа для асинхронного кода и коллбеков в Unity