2009-08-07 46 views
3

下面是一些用於傳遞對包含字符串作爲參數的方法的引用的代碼,此問題的目的是圍繞使用泛型否定需要定義實際的類型!將方法傳遞到需要方法名稱的另一個方法

Impossible<ExampleSource, string>.Example(c => c.NonString); //does not work 
Impossible<ExampleSource, string>.Example<int>(c => c.NonString); //does work 

這裏的想法是讓第一個「非字符串」呼叫工作,而不必定義參數類型或聲明不可能在一個新的函數,它Func鍵< INT,TResult >。

public static void Example(Expression<Func<TSource, Func<int, TResult>>> function) 
    { Process(function as MethodCallExpression); } //invalid solution... 

在Java中,這可能使用Func鍵<?來實現,TResult >

public class Impossible<TSource, TResult> 
{ 
    public static void Example(Expression<Func<TSource, Func<TResult>>> function) 
     { Process(function as MethodCallExpression); } 
    public static void Example(Expression<Func<TSource, Func<string, TResult>>> function) 
     { Process(function as MethodCallExpression); } 
    public static void Example(Expression<Func<TSource, Func<string, string, TResult>>> function) 
     { Process(function as MethodCallExpression); } 

    public static void Example<T1>(Expression<Func<TSource, Func<T1, TResult>>> function) 
    { Process(function as MethodCallExpression); } 
    public static void Example<T1, T2>(Expression<Func<TSource, Func<T1, T2, TResult>>> function) 
    { Process(function as MethodCallExpression); } 

    private static void Process(MethodCallExpression exp) 
    { 
     if (exp == null) return; 
     Console.WriteLine(exp.Method.Name); 
    } 
} 

public class ExampleSource 
{ 
    public string NoParams() { return ""; } 
    public string OneParam(string one) { return ""; } 
    public string TwoParams(string one, string two) { return ""; } 
    public string NonString(int i) { return ""; } 
} 

public class Consumer 
{ 
    public void Argh() 
    { 
     Impossible<ExampleSource, string>.Example(c => c.NoParams); 
     Impossible<ExampleSource, string>.Example(c => c.OneParam); 
     Impossible<ExampleSource, string>.Example(c => c.TwoParams); 
     Impossible<ExampleSource, string>.Example<int>(c => c.NonString); 
     Impossible<ExampleSource, string>.Example(c => c.NonString); //MAKE THIS WORK 
    } 
} 
+0

我想我真的不明白的問題是什麼?如何使用委託? – chills42 2009-08-07 19:06:56

+0

問題是我怎麼可以可以我推斷出T1到T4的參數類型,將代碼複製到程序中並編譯。 – bleevo 2009-08-08 00:32:19

回答

0

它看起來越來越像這種無法做到:(

+0

經過進一步的研究,沒有簡單的方法來支持這種方法,我將使用T4模板進行探索。 – bleevo 2009-08-17 00:37:53

+0

這就是Noldorin的回答,爲什麼不接受他更詳細的答案? – nawfal 2013-04-27 14:57:28

0

最明確,最強的打字我能想出這個職位的問題部分上市:

Why is there not a fieldof or methodof operator in C#?

要頂到,我需要更多地瞭解你的目標是什麼(這裏有更大的圖片)。

+0

這裏的最終目標是通過查找基於類型的路由來傳遞ASP.NET MVC的方法名稱以生成URL該方法的不打算(「的MyMethod」),但在控制器和名稱的相當(C => c.MyMethod),其中的參數的類型的MyMethod取心不是重要或它的返回只需輸入它的名稱即可。 – bleevo 2010-07-10 04:08:03

0

沒有辦法做到這一點,因爲方法解決方法總是適用於返回類型和參數的組合,但不僅限於返回類型。我剛剛在其他帖子中發佈的原因是,問題在這裏。爲什麼C#不僅不同的返回類型提供方法解析原因是以下...

public class Test{ 
    public int DoMethod(){ return 2; } 
    public string DoMethod() { return "Name"; } 
} 
Test t; 
int n = t.DoMethod(); // 1st method 
string txt = t.DoMethod(); // 2nd method 
object x = t.DoMethod(); // DOOMED ... which one?? 

如果你注意到,在最後聲明中,編程語言有選擇哪種方法沒有正確的解決方案。

這是完全一樣的原因,下面的代碼無法正常工作......

public class Test{ 
    public T ReturnEmpty<T>() { return default(T); } 
    public T ReturnEmpty<T>(T x) { return x; } 
} 
Test t = new Test(); 
int n = t.ReturnEmpty(); <--- does not work.. 
           the reson check next statement... 
object k = t.ReturnEmpty(); <--- which one... 
int l = t.ReturnEmpty<int>(); <--- this is correct.... 
string m = t.ReturnEmpty("Do Test"); <-- this is correct... 

所以再次,相同的解決方案,解決僅基於返回類型的方法爲任何一個編譯器解決方案abigious。編程語言與口頭語言不同,因爲它們的設計始終是「一種執行方式」,沒有歧義,也沒有上下文依賴關係。每個陳述都完全獨立於上下文。

然而,你可以爭辯說你有正確的返回類型,但事實並非總是如此,編譯器需要強大的規則來編譯和生成代碼。

+0

關於:object k = t.ReturnEmpty();編譯器可能會在這一個上返回一個錯誤,說明沒有辦法隱式地定義需要在這裏調用哪個方法。但是這會帶來額外的複雜性。 此外鍵入推論不會工作,原因很明顯... – Ray 2009-08-11 12:42:43

+0

這個問題與方法解析無關,而是泛型類型參數解析,這是由C#編譯器完全分開完成的。 – Noldorin 2009-08-11 12:43:13

+0

@Ray,@Noldorin我知道這些錯誤,並且您是否調用泛型類型參數解析或方法重新解析,解析需求的規則不可能是模糊的,那就是我想解釋的是,這不可能由替代例。 – 2009-08-11 12:55:07

3

簡單的答案是否定的,在最新版本的C#中這是不可能的。方法調用的泛型類型參數的推理只是不夠聰明,不足以實現您傳遞的方法返回int。因此,你不得不自己指定它。

通過閱讀C# Language Specification的部分14.5.5.1可以找到長答案。雖然它在這個特定情況下並不直接,但它確實暗示了你所希望的那種類型推斷是不可能的。請仔細閱讀該部分和25中的相應文字,並且您應該知道所有關於泛型類型參數及其推斷的知識。

希望有所幫助。如果您需要對特定部件進行任何說明,請告知我們。

+0

雖然不是一個解決方案,我想你已經證實了我相信這心不是可能的,我不打算T4模板和大量的方法重載的是唯一的方法:( – bleevo 2009-08-14 05:48:09

+0

是啊,除非我誤會了,沒有解決問題的方法(而不是直接的,至少)你是否可能澄清到底爲什麼你必須有推斷的類型,而不是明確指定呢? – Noldorin 2009-08-14 11:36:53

0

你可以添加這不可能<>類接受<int, TResult>通話?

public static void Example(Expression<Func<TSource, Func<int, TResult>>> function) 
{ Process(function as MethodCallExpression); } 
+0

正如你會看到這個方法的問題是不可接受的,因爲我必須爲每種類型和類型的組合做到這一點。 – bleevo 2009-08-14 05:46:59

+0

對不起,我誤解了。我應該在回答之前重新閱讀這個問題。我不認爲有一個解決方案適合你的問題約束 – ongle 2009-08-14 12:45:05

相關問題