2012-08-13 9 views
10

Jeśli mam lambdę taką jak () => { throw new Exception(); }, nie jest jasne, czy ma ona typ powrotu, czy nie. Z tego powodu może być (niejawnie) przekonwertowany zarówno na Action i Func<object> (lub dowolny inny Func<T>). Ma to miejsce dlatego, że zgodnie z § 6.5 Anonymous konwersji funkcji z C# 4 specyfikacji:Konwersja Lambda z niejasnym typem powrotu i rozdzielczością przeciążenia

[A], pełnomocnik typu D jest zgodny z anonimową funkcję F warunkiem, że:

  • ...

  • Jeśli D ma void typ zwrotu, a treść F jest blokiem instrukcji, gdy [...] treścią jest F jest poprawnym blokiem instrukcji, w którym żadna instrukcja return nie określa wyrażenia.

  • Jeśli D ma nie zwracać typ void i ciało F jest blok oświadczenie, gdy [...] ciało F jest ważny blok oświadczenie o nie osiągalnego punktu końcowego, w którym każdy return Instrukcja Określa wyrażenie, które jest niejawnie zamienne na typ zwrotu D.

Ale jeśli dwie przeciążeń dotyczące sposobu, w której ma się parametr typu Action a drugi Func<object>, i przekazać je lambda od powyżej, stosuje się przeciążenia Func<object>. Czemu? Która część specyfikacji mówi, że w tym przypadku Func<object> jest lepsza niż Action?

Przyjrzałem się § 7.5.3.2 Lepszy członek funkcji, ale to nie wyjaśnia.

+0

A jeśli zamiast składni lambda, należy użyć notacja 'delegate {throw new Exception(); } 'gdzie pominąć listę parametrów w nawiasach'() ', że anonimowa funkcja może pasować ** dowolnie ** podpis delegata, w tym także np. Obiekty 'EventHandler' i' Action <, EventArgs> '. –

+0

@JeppeStigNielsen Yeah. W takim przypadku tak naprawdę nie ma reguły, która pozwalałaby je rozróżnić jako parametry metody, więc powstałby błąd kompilacji. – svick

Odpowiedz

11

Powinienem wyglądać o jeden punkt niżej: §7.5.3.3 Lepsza konwersja z wyrażeniem wyjaśnia, że:

Biorąc niejawna konwersja C1 który konwertuje z wyrazem E do rodzaju T1 i niejawna konwersja C2, który konwertuje z wyrazem E do rodzaju T2, C1 jest lepszą konwersję niż C2, jeśli co najmniej jeden z poniższych warunków:

  • ...

  • E jest anonimowa funkcja, T1 to albo typ delegata D1 lub rodzaj drzewa wyrażenie Expression<D1>, T2 to albo typ delegata D2 albo drzewo rodzaj ekspresji Expression<D2> i jeden z poniższych warunków:

    • ...

    • D1 i D2 mają identyczne listy parametrów, a jeden z poniższych warunków:

      • ...

      • D1 ma typ zwracanej Y i D2 jest nieważna powrocie

+1

Wysłałeś tę odpowiedź w tym samym momencie, w którym zadałeś pytanie? –

+6

Tak, podczas pisania tego pytania zauważyłem odpowiedź w specyfikacji. Więc nie chciałem marnować czasu na badanie tego. Ale w tym samym czasie myślałem, że może to być przydatne dla kogoś innego. – svick

+1

Ta odpowiedź wyjaśnia, w jaki sposób zaobserwowane zachowanie pasuje do specyfikacji, ale nie wyjaśnia (i nie może), dlaczego specyfikacja została napisana w ten sposób w pierwszej kolejności. Na szczęście [mamy teraz słowo] (http://stackoverflow.com/questions/24316189/peculiar-overload-resolution- with-while-true/24316474?noredirect=1#comment37681268_24316474) od osoby, która zaimplementowała tę funkcję w kompilator również to wyjaśnia! – Jon

Powiązane problemy