Func <T> () vs Func <T> .Invoke ()

83

Jestem ciekawy różnic między bezpośrednim wywołaniem Func a użyciem na nim Invoke (). Czy jest jakaś różnica? Czy pierwszy to cukier składniowy i wywołuje Invoke () pod spodem?

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

vs

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

Czy też jestem na złej drodze :) Dzięki.

tris
źródło

Odpowiedzi:

113

Nie ma żadnej różnicy. Drugi jest tylko skrótem Invoke, dostarczonym przez kompilator. Kompilują się do tego samego IL.

Jon Skeet
źródło
1
Pozostawienie wyłączonej metody Invoke () powoduje błąd kompilatora: „Nie można niejawnie przekonwertować typu„ System.Func <T> ”na„ T ””. Kompiluję przeciwko .NET 4.
Mike,
2
@Mike: To by się zdarzyło, gdybyś również pominął nawiasy - tj. Próbowałbyś (T)methodraczej wrócić niż (T)method().
Jon Skeet,
@JonSkeet Czy ten facet się myli tutaj: social.msdn.microsoft.com/Forums/en-US/ ...
superlogical
4
@superlogical: Występują tutaj dwa problemy. Po pierwsze, pytanie dotyczy różnicy między wywołaniem metody bezpośrednio a wywołaniem jej przez delegata. To nie to samo, co różnica między foo()i foo.Invoke()gdzie foojest zmienną typu delegata. Innym problemem jest to, że odpowiedź wydaje się mówić Control.Invoke, co nie jest tym samym, co wezwanie Invokedelegata.
Jon Skeet
2
@LucaCremonesi: Jeśli jest to wynik wywołania metody, generalnie mi się podoba Invoke, bo GetAction()()wygląda dziwnie, ale GetAction().Invoke()wygląda dobrze. Ale w większości nie mam nic przeciwko temu.
Jon Skeet
17

Invoke działa dobrze z nowym operatorem propagacji wartości null w języku C # 6, teraz możesz to zrobić

T result = method?.Invoke();

zamiast

T result = method != null ? method() : null;
sanjuro
źródło
Czy możesz zilustrować scenariusz, w którym jest to przydatne? Przypadek podręcznika wywołuje wydarzenia.
Gusdor,
1
Na przykład możesz mieć opcjonalny parametr Func, który jeśli nie zostanie przypisana żadna wartość, będzie wartością domyślną (Func), która ma wartość null i jest ignorowana.
Austin Salgat
1
Jest to typowy przypadek dla zdarzeń i innych delegatów rzutowania wielokrotnego - są one zwykle inicjowane z wartością null i uzyskują wartość inną niż null po wywołaniu +=. Więc jeśli masz zamiar uruchomić wydarzenie i nie wiesz, czy są jakieś subskrypcje, zwięzłym rozwiązaniem jest zadzwonić ?.Invoke(...).
stop-cran