Ну, есть ключевое слово delegate — это описание сигнатуры функции, т. е., её списка параметров и типа возвращаемого значения. Используется так:
1 |
public delegate bool MyPredicate(int x); |
Им можно пользоваться так:
1 2 3 4 5 6 7 8 9 10 |
private bool IsOdd(int i) { return i % 2 != 0; } private Analyze(MyPredicate p, int x) { bool result = p(x); if (result) Console.WriteLine("found!"); } Analyze(IsOdd, 1); // печатает "found!" |
С другой стороны, есть готовые, предопределённые сигнатуры функций (Func<TArg1, TArg2, ..., TResult>
с возвращаемым значением, Action<TArg1, Targ2, ...>
без). То есть, можно не определять делегат самому, а воспользоваться готовыми Func
и Action
. Аналогичный пример:
1 2 3 4 5 6 7 8 9 10 |
private bool IsOdd(int i) { return i % 2 != 0; } private Analyze(Func<int, bool> p, int x) { bool result = p(x); if (result) Console.WriteLine("found!"); } Analyze(IsOdd, 1); // печатает "found!" |
Если для вашей сигнатуры подходит Func
или Action
, особого смысла определять свой делегат нету. Или есть, если вы хотите дать своему делегату более подходящее имя, чем просто Func
, и хотите подчеркнуть его семантику.
Существуют случаи, когда свой делегат всё же необходимо объявлять. Например, наличие out
– и ref
-параметров:
1 |
public delegate Updater(ref int x); // невозможно выразить через Func |
Для полноты, вот (надеюсь, полный) список вариантов, когда вам придётся объявлять делегат:
- Когда список аргументов чересчур длинный (для .NET 4+ более 16 аргументов, для .NET 3.5 больше 4 аргументов)
- Когда ваши аргументы содержат
ref
,out
илиparams
. - Если ваш делегат рекурсивен (например
delegate D D(D d)
). Как ни странно, такие штуки иногда нужны.