它不能推斷出類型,因爲這裏沒有定義類型。
Fun2
不是Func<string, string>
,它是可以分配給Func<string, string>
的東西。
所以如果你使用:
public Test()
{
Func<string, string> del = Fun2;
Fun(del);
}
或者:
public Test()
{
Fun((Func<string, string>)Fun2);
}
就會明確地從Fun2
創建Func<string, string>
,和通用類型推斷相應的工作。
相反,當你這樣做:
public Test()
{
Fun<string>(Fun2);
}
那麼集合重載Fun<string>
的只包含一個接受一個Func<string, string>
,編譯器可以推斷,要使用Fun2
這樣。
但是你問它來推斷都基於參數的類型泛型類型,並根據泛型類型參數的類型。這是一個比它可以做的任何推斷類型都要大的問題。
(這是值得考慮的是,在.NET 1.0不僅是代表不是通用的,所以你將不得不定義delgate string MyDelegate(string test)
- 但它也有必要與構造Fun(new MyDelegate(Fun2))
創建對象。語法已更改爲使用的代表更容易以多種方式進行,但隱含地使用Fun2
作爲Func<string, string>
仍然是幕後代表對象的構造)。
那麼,爲什麼這個工程?
class Test
{
public void Fun<T1, T2>(T1 a, Func<T1, T2> f)
{
}
public string Fun2(int test)
{
return test.ToString();
}
public Test()
{
Fun(0, Fun2);
}
}
因爲那麼它可以推斷出,爲了:
T1
是int
。
Fun2
被分配到Func<int, T2>
一些T2
。
Fun2
可以分配給一個Func<int, T2>
如果T2
是string
。因此T2
是字符串。
特別是,返回類型Func
可以從函數中推斷出來,只要你有參數類型。這也是一樣的(值得編譯器付出努力),因爲它在Linq的Select
中很重要。這引起了一個相關的案例,事實是隻有x.Select(i => i.ToString())
我們沒有足夠的信息來知道lambda轉換爲什麼。一旦我們知道了x
是IEnumerable<T>
或IQueryable<T>
我們知道,我們要麼有Func<T, ?>
或Expression<Func<T, ?>>
,其餘的可以從那裏推斷。
這也是這裏值得注意的,即推斷返回類型是不受的模糊性推導的其他類型。考慮如果我們的Fun2
(需要string
和int
)在同一個班級。這是有效的C#重載,但會扣除Func<T, string>
的類型Fun2
可以投射到不可能;兩者都是有效的。
但是,雖然.NET允許在返回類型上重載,但C#沒有。因此,一旦確定了T
的類型,則從方法(或lambda)創建的Func<T, TResult>
的返回類型中沒有有效的C#程序可能不明確。這相對容易,加上巨大的用處,使得編譯器可以很好地爲我們推斷。
重新編輯,您現在已經提供了編譯器 - 通過「Fun(0,Fun2)」調用。編譯器現在知道它需要一個方法,來自'Fun2'方法組,它有'T1'類型,在這種情況下'int'。這將其縮小爲一種方法,因此可以推斷使用哪一種方法。 –
但是首先有一個Fun2,所以它不會真正「縮小」任何東西。 –
C#編譯器拒絕將僅包含一個方法的方法組作爲委託來處理。您必須提供信息才能從組中選擇一種方法,以便爲此而煩惱。如果它看着這個團隊,意識到只有一種方法並選擇了它,那很好,但可悲的是,這不是它的工作原理。 –