2016-03-31 36 views
1

我一直在C#中進行類型推理,我已經閱讀了this thread。正如在線程中所述,類型推斷不適用於泛型委託(當您將方法傳遞給此委託參數而沒有任何顯式轉型時),例如Func,Action等。然後,我想嘗試LINQ運算符,如SelectMany和.net Func類而不是lambda表達式來查看結果。但是,這不是我預期的結果。類型推斷代理參數的方法

我創建了一個名爲L1的測試類,其中包含一個字符串列表以便在SelectMany中使用(展平)。除此之外,我創建了一個測試方法來傳遞而不是Func類型參數。

public class L1 
{ 
    private L1() {} 

    public L1(string m) 
    { 
     Isim = m; 
     numbers = new List<string> { "1", "2", "3", "4", "5" }; 
    } 

    public List<string> numbers; 
    public string Isim { get; private set; } 
} 
private static IEnumerable<int> a(L1 k) 
{ 
    return Enumerable.Empty<int>(); 
} 

當我創建類似下面的擴展方法,C#編譯器不能推論通用參數的類型。

public static void Test<T1, T2>(this L1 l, Func<T1, IEnumerable<T2>> a) 
{ 
} 

(new L1("test")).Test(a); 

它給出「錯誤CS0411:用於方法的類型參數 'EnumSand.Test(L1,Func鍵>)' 不能從使用推斷。嘗試明確指定類型參數。'正如我所預期的那樣。

但是,當我在LINQ SelectMany擴展方法中使用此方法a時,編譯器不會給出任何錯誤並且它可以工作。

L1[] l1 = new L1[5] { 
         new L1("one"), new L1("two"), 
         new L1("three"), new L1("four"), 
         new L1("five") 
        }; 

var slack = l1.SelectMany(a); 

foreach (var t in slack) 
{ 
    Console.WriteLine(t); 
} 

那麼,是這些案件和它是如何可能的SelectMany中進行了良好的類型推斷的區別?

回答

2

的問題是在這裏:

public static void Test<T1, T2>(this L1 l, Func<T1, IEnumerable<T2>> a) 

T2勢必intT1可以是任何東西,這就是爲什麼它無法推斷。

您可以更改第二個參數Func<L1, IEnmuerable<T2>>和完全刪除T1或更改this L1this T1

編輯: 考慮當你有以下方法的情況:

private static IEnumerable<int> a(L1 k) 
{ 
    return Enumerable.Empty<int>(); 
} 

private static IEnumerable<int> a(string k) 
{ 
    return Enumerable.Empty<int>(); 
} 

現在你能說哪個a方法應該用於(new L1("test")).Test(a);用?

+0

你的意思是編譯器可以從返回類型入手,但不是從參數? 'Func >'SelectMany'簽名中的selector'由於擴展方法規則已經知道'TSource',在這種情況下返回類型推斷就足夠了? – Deniz

+0

@Deniz,我同意這個答案。這並不意味着編譯器可以從返回類型推斷,但不能從參數推斷。不知道,爲什麼你會這麼想。 –

+0

@AndrewSavinykh,我試着將T1變成L1,結果相同。 – Deniz

相關問題