2014-02-13 28 views
2

當運行此程序我得到含有FN(3,4)行兩個錯誤C#Func鍵<>代表參數轉換錯誤

參數1:不能從 'INT' 轉換到T

參數2:無法從'int'轉換爲T

我認爲類型T將是int,如lambda指定的。但如果是這樣,那麼爲什麼轉換錯誤?我誤解了什麼嗎?

class Program 
{ 
    static void DoStuff<T>(Func<T, T, T> fn) 
    { 
     Console.WriteLine(fn(3, 4)); 
    } 

    static void Main() 
    { 
     DoStuff((int x, int y) => x + y); 
    } 
} 

這工作,如果我改變參數接受整數作爲參數:

class Program 
{ 
    static void DoStuff<T>(T x, T y, Func<T, T, T> fn) 
    { 
     Console.WriteLine(fn(x, y)); 
    } 

    static void Main() 
    { 
     DoStuff(3, 4, (int x, int y) => x + y); 
    } 
} 

我來自一個C++的背景,所以試圖讓我的頭周圍什麼可行,什麼不可行在C#

+1

這是不允許的,因爲對於像'DoStuff '這樣的東西,它是無效的。泛型不像C++模板那樣工作,如果這就是你所想的。 – hvd

回答

8

裏面DoStuff<T>方法中,T的實際類型是未知的;您的代碼將int s到的功能,假設Tint,但T實際上可能是任何東西,像string,所以你會路過int s到只接受string個功能。


RE「我來自一個C++的背景,所以試圖讓我的頭周圍什麼可行,什麼不可行的C#」:

C#泛型類似於C++模板,但他們實際上完全不同。

  • 在C++中,模板在編譯時根據用法被實例化;如果對T使用3種不同類型的模板方法,編譯器將生成3種不同的方法。對於任何T,模板方法的主體不一定是有效的,只要它對實際使用情況有效即可。 (抱歉,如果我的解釋是不完全準確的,我不知道C++非常好)

  • 在C#中,有基於使用沒有編譯時生成;編譯器僅生成1個通用方法,並且運行時會生成給定T的實際運行時方法。爲了確保這將工作,在C#編譯器必須確保該方法體有效期爲任何T(或者,如果你指定的約束T,任何T這些約束相匹配)。這就是爲什麼你在你的第一個片段得到一個錯誤:通用方法的主體只能是有效的,如果Tint

我建議你閱讀的答案this question了更詳細的解釋。

+0

謝謝。我編輯了我的帖子以顯示工作片段...你能解釋爲什麼這會起作用嗎? – PowerApp101

+0

@ 20thCenturyBoy,這是有效的,因爲指定的參數是調用地點,其中'T'的實際類型是已知的。 –

+0

@ 20thCenturyBoy,我更新了我的答案,以解釋C++模板和C#泛型之間的區別 –

1

這裏不需要使用泛型。改變

static void DoStuff<T>(Func<T, T, T> fn) 

static void DoStuff(Func<int, int, int> fn) 
+0

是的,我知道這樣做,但我想了解爲什麼通用版本不能推斷類型T爲int。 – PowerApp101

+0

@ 20thCenturyBoy因爲泛型類型推斷髮生在調用站點,而不是在方法定義中。在方法定義中推斷參數類型是沒有意義的,因爲那麼該方法首先不是通用的。 – Kyle

+0

@凱爾我明白你的意思了。我只是認爲在調用網站的lambda中包含的類型信息足以推斷出類型T,即lambda指定了ints。 – PowerApp101

相關問題