Страницы

Поиск по вопросам

среда, 27 ноября 2019 г.

В чем разница между Func<> и delegate?

#c_sharp


Оба варианта используются с целью возвращения значения, оба могут принимать несколько
параметров.
В чем между ними разница?
    


Ответы

Ответ 1



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

Ответ 2



А вы вообще уверены, что правильно понимаете, что такое делегат? Так вот, делегат в c# - это такая сущность, которая может представлять собой некий метод. Можно сказать, что делегат определяет сигнатуру метода и его возвращаемое значение. (а можно также сказать, что делегат - это такой указатель на функцию, как, скажем, в С++, но с некотрыми оговорками). Так вот Func (и любая его разновидность в том числе) - это всего лишь разновидность делегата. То есть любой Func - делегат, но не любой делегат - Func и сравнивать их не очень уместно. А что касается этого: Оба используются я целью возвращения значения, оба могут принимать несколько параметров то вот вам пример делегата, который не принимает аргументов и не возвращает значений: delegate void SomeDelegate();

Ответ 3



Если посмотреть описание Func то он является дженерик делегатом namespace System { /// Инкапсулирует метод с одним параметром и возвращает значение типа, указанного в параметре . /// Возвращаемое значение метода, инкапсулируемого данным делегатом. /// Параметр метода, инкапсулируемого данным делегатом. /// Тип параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип. Дополнительные сведения о ковариации и контрвариации см. в разделе Ковариация и контравариация в универсальных шаблонах. /// Тип возвращаемого значения метода, инкапсулируемого данным делегатом.Этот параметр типа является ковариантным. Это означает, что можно использовать либо указанный тип, либо более производный тип. Дополнительные сведения о ковариации и контрвариации см. в разделе Ковариация и контравариация в универсальных шаблонах. /// 2 [__DynamicallyInvokable, TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] public delegate TResult Func(T arg); } Использование Func удобнее нежели каждый раз объявлять конкретный делегат, а так как он находится в mscorlib.dll то доступен из всех сборок.

Комментариев нет:

Отправить комментарий