Func <T> () против Func <T> .Invoke ()

83

Мне любопытно узнать о различиях между прямым вызовом Func и использованием на нем Invoke (). Есть разница? Является ли первый синтаксический сахар и в любом случае вызывает Invoke () внизу?

public T DoWork<T>(Func<T> method)
{
    return (T)method.Invoke();
}

против

public T DoWork<T>(Func<T> method)
{
    return (T)method();
}

Или я совершенно ошибаюсь :) Спасибо.

трис
источник

Ответы:

113

Вообще нет никакой разницы. Второй - это просто сокращение Invoke, предоставленное компилятором. Они компилируются в один и тот же IL.

Джон Скит
источник
1
Отключение метода Invoke () приводит к ошибке компилятора: «Невозможно неявно преобразовать тип 'System.Func <T>' в 'T'». Я компилирую против .NET 4.
Майк
2
@Mike: Это могло бы случиться, если бы вы тоже пропустили скобки, то есть попытались бы вернуться, (T)methodа не (T)method().
Джон Скит
@JonSkeet Так этот парень неправильно здесь: social.msdn.microsoft.com/Forums/en-US/...
superlogical
4
@superlogical: Здесь есть две проблемы. Во-первых, вопрос заключается в разнице между прямым вызовом метода и его вызовом через делегата. Это не то же самое, что разница между foo()и foo.Invoke()где foo- переменная типа делегата. Другая проблема заключается в том, что ответ, похоже, говорит о том Control.Invoke, что это не то же самое, что вызов Invokeделегата.
Джон Скит
2
@LucaCremonesi: Если это результат вызова метода, мне обычно нравится Invoke, так как GetAction()()выглядит странно, но GetAction().Invoke()выглядит нормально. Но я в любом случае не возражаю, по большей части.
Джон Скит
17

Invoke хорошо работает с новым оператором нулевого распространения C # 6, теперь вы можете

T result = method?.Invoke();

вместо

T result = method != null ? method() : null;
сандзюро
источник
Можете ли вы проиллюстрировать сценарий, в котором это будет полезно? Случай из учебника поднимает события.
Gusdor
1
Например, у вас может быть необязательный параметр Func, который, если значение не назначено, является значением по умолчанию (Func), которое имеет значение NULL и игнорируется.
Остин Салгат,
1
Это обычный случай для событий и других многоадресных делегатов - они обычно инициализируются нулевым значением и после вызова получают ненулевое значение +=. Поэтому, если вы собираетесь запустить событие и не знаете, есть ли какие-либо подписки, краткое решение - позвонить ?.Invoke(...).
stop-Cran