将方法传递给需要方法名称的另一个方法

时间:2009-08-07 04:52:07

标签: .net

下面是一些代码,用于传递对包含字符串作为参数的方法的引用,这个问题的目的是使用泛型来否定定义实际类型的需要!

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

这里的想法是让第一个“NonString”调用工作,而不必定义参数类型或在Impossible中声明一个新函数,它接受Func&lt; int,TResult&gt;。

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

在Java中,可以使用Func&lt;?,TResult&gt;

来实现
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
    }
}

5 个答案:

答案 0 :(得分:3)

简单的答案是否定的,这在最新版本的C#中是不可能的。方法调用的泛型类型参数的推断并不足以实现您传递的方法返回int。因此,您必须自己指定它。

通过阅读C# Language Specification14.5.5.1部分,可以找到答案很长的答案。虽然它在这个特定情况下远非直接,但它隐含地说明了您希望的那种类型推断是不可能的。仔细阅读该部分以及25部分中的相应文本,您应该知道所有关于泛型类型参数及其推断的知识。

希望有所帮助。如果您需要对特定部分进行任何澄清,请与我们联系。

答案 1 :(得分:0)

本文的问题部分列出了我能提出的最明确,最强的打字:

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

最重要的是,我需要更多地了解你的目标是什么(这里有更大的图片)。

答案 2 :(得分: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...

因此,同样的解决方案,仅基于返回类型的解析方法对于任何编译器来说都是一个可行的解决方案。编程语言与口语不同,因为它们旨在始终只提供“一种执行方式”,没有歧义,也没有上下文依赖。每个语句都完全独立于上下文。

但是你可以说你有正确的返回类型,但情况可能并非总是如此,编译器需要强大的规则来编译和生成代码。

答案 3 :(得分:0)

你可以将它添加到Impossible&lt;&gt; class接受<int, TResult>调用??

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

答案 4 :(得分:0)

它看起来越来越像这样:(