2012-06-09 13 views
6

Nie jestem facet C# Jestem bardziej obiektywnej-C facet, ale ostatnio widziałem wiele wdrożeń:Action <T> vs standardowa Powrót

public void Method(Action<ReturnType> callback, params...) 

Zamiast:

public ReturnType Method(params...) 

Jednym z przykładów tego jest MVVM Light Framework, tam programista implementuje umowę o usługi danych (i wdrożenie) przy użyciu pierwszego podejścia, więc moje pytanie brzmi: dlaczego to? Jest tylko kwestią polubień lub jest pierwszym podejściem asyncronous przez defaut (biorąc pod uwagę wskaźnik funkcji). Jeśli to prawda, czy standardowa śmierć wraca? Pytam, ponieważ osobiście podoba mi się, że drugie podejście jest dla mnie bardziej zrozumiałe, gdy widzę API.

+0

Jeśli nie masz już możliwości, to z Biblioteką zadań (Task Parallel Library) biblioteki oferujące metody asynchroniczne * zazwyczaj * oferują metodę Task (params ...) zamiast odbierać wywołania zwrotnego, ale to może nie być opcja dla bibliotek, które muszą pracować ze strukturami, które nie mają obsługi Task (na przykład, Silverlight dostał zadanie dodane w wersji 5, więc wszystko, co Silverlight 4 lub wcześniej musiałby trzymać z callbackami lub jakimś innym wzorcem) –

+0

@JamesManning Widziałem implementacje licencji TPL, która wygląda dość jasno. Czy oni są tylko coverami - tak samo? –

+0

Myślę, że to zależy od tego, czym jest biblioteka implementująca. Koncepcyjnie, TPL jest trochę "lepsza" (IMHO), ponieważ obsługuje takie rzeczy jak anulowanie i wyjątki.Dzięki nowym funkcjom językowym możesz również napisać, co "czuje" się jak kod synchroniczny, używając oczekiwanego słowa kluczowego, co pozwala uniknąć konieczności pisania metod wywoływania zwrotnego, pozwalając kompilatorowi przepisać metodę, aby to zrobić dla ciebie. –

Odpowiedz

10

W odróżnieniu od interfejsu API zwracającego ReturnType, wersja z funkcją zwrotną może natychmiast wrócić i wykonać później wywołanie zwrotne. Może to być ważne, gdy wartość zwrotu nie jest natychmiast dostępna, a uzyskanie jej pociąga za sobą znaczne opóźnienie. Na przykład interfejs API żądający danych z usługi sieciowej może zająć dużo czasu. Gdy dane wynikowe nie są wymagane do kontynuowania, można zainicjować połączenie i zapewnić asynchroniczne wywołanie zwrotne. W ten sposób dzwoniący będzie mógł od razu przystąpić do działania i będzie przetwarzał powiadomienia, gdy staną się dostępne.

Rozważ interfejs API, który pobiera adres URL obrazu i zwraca reprezentację obrazu w pamięci. Jeśli API jest

Image GetImage(URL url) 

i użytkownicy muszą ciągnąć dziesięć obrazów, to oni albo trzeba czekać na każdy obraz, aby zakończyć ładowanie przed wezwaniem następny, lub rozpocząć wiele wątków wyraźnie.

Z drugiej strony, jeśli API jest

void Method(Action<Image> callback, URL url) 

następnie użytkownicy swojej API byłoby zainicjować wszystkie dziesięć żądań w tym samym czasie, i wyświetlać obrazy stają się one dostępne asynchronicznie. Takie podejście znacznie upraszcza programowanie wątków wymagane przez użytkowników.

+0

Czy znasz jakiś odpowiednik w Javie? – dantuch

+2

@dantuch Java nie ma delegatów, więc nie ma bezpośredniego odpowiednika. Ale możesz zrobić coś podobnego za pomocą interfejsu za pomocą jednej metody. I możesz użyć anonimowej klasy, aby ją zaimplementować. – svick

3

Pierwsza metoda może być metodą asynchroniczną, gdzie metoda zwraca się natychmiast, a wywołanie zwrotne jest wywoływane po zakończeniu operacji.

Druga metoda to standardowy sposób wykonywania zwracanych metod dla metod (synchronicznych) w języku C#.

Oczywiście projektanci interfejsów API mogą dowolnie określać podpis; i mogą istnieć inne podstawowe szczegóły, które usprawiedliwiają styl wywołania zwrotnego. Ale, z reguły, jeśli widzisz styl wywołania zwrotnego, spodziewaj się, że metoda będzie asynchronusem.