2012-08-13 41 views
10

如果我有一個lambda如() => { throw new Exception(); },目前還不清楚它是否有返回類型或沒有。正因爲如此,它可以是(隱式地)轉換爲兩個ActionFunc<object>(或任何其它Func<T>)。這是因爲,根據§6.5匿名功能轉換的C#4規範的LAMBDA轉換不清的返回類型和重載決議

[A]委託類型D是與設置一個匿名函數F兼容:

  • ...

  • 如果D有一個void返回類型,並且F的主體是語句塊,當的主體10是一個有效的語句塊,其中沒有return語句指定表達式。

  • 如果D具有非void返回類型和F主體是一個語句塊,當[...]的F主體是具有非可到達終點的有效語句塊,其中每個return語句指定可隱式轉換到的D返回類型的表達式。

但是,如果我有一個方法,其中,一個具有Action類型和其他Func<object>的參數的兩個重載,我通過它從上面的拉姆達,則使用Func<object>過載。爲什麼?其規範的一部分,說Func<object>比在這種情況下Action更好?

我已經看過§7.5.3.2更好的功能成員,但這並不能解釋它。

+0

而如果代替lambda語法,你用符號'委託{拋出新的異常(); }'在'(')'括號中省略參數列表,那個匿名函數可以匹配**我猜想的任何**委託簽名,包括例如'EventHandler'和'Action '。 – 2012-08-13 20:41:20

+0

@JeppeStigNielsen是的。在這種情況下,確實沒有規則可以將它們作爲方法參數消除歧義,所以你會得到一個編譯錯誤。 – svick 2012-08-13 20:59:52

回答

11

我已經看了一個部下:第7.5.3節。從表達更好的轉換解釋說:

鑑於從表達式E轉換到類型T1,而且從表達式E轉換到類型T2的隱式轉換C2的隱式轉換C1C1是比C2更好的轉換,如果以下的至少一人持有:

  • ...

  • E是匿名函數,T1或者是委託類型D1或表達式樹類型Expression<D1>T2或者是委託類型D2或表達式樹類型Expression<D2>和以下中的一個成立:

    • ...

    • D1D2具有相同的參數列表,以及以下情況之一成立:

      • ...

      • D1有一個返回類型Y,並且D2無效返回

+1

你已經在問這個問題的同一秒發佈了這個答案嗎? – 2012-08-13 20:44:36

+6

是的,當我寫這個問題時,我注意到了規範中的答案。所以我不想浪費任何人的時間來研究這一點。但同時,我認爲這可能對其他人有用。 – svick 2012-08-13 20:51:36

+1

這個答案解釋了觀察到的行爲如何符合規範,但是它沒有(也不能)解釋爲什麼規範是這樣寫的。幸運的是,[我們現在擁有這個詞](http://stackoverflow.com/questions/24316189/peculiar-overload-resolution-with-while-true/24316474?noredirect=1#comment37681268_24316474)來自執行該功能的人編譯器解釋這一點! – Jon 2014-06-24 16:18:00