为什么添加返回类型会阻止我使用方法组语法?

时间:2010-10-22 10:13:13

标签: c# lambda method-group

我正在尝试在lambda表达式中使用方法组,如下所示:

public class Foo { public void Hello(string s) { } }

void Test()
{
    // this works as long as Hello has a void return type
    Func<Foo, Action<string>> a = foo => foo.Hello;
}

当我将Hello的返回类型更改为int时,我得到了

  

'Bar.Hello(string)'的返回类型错误。

我尝试使用Func代替Action,但这似乎阻止我使用方法组语法。

有什么想法吗?

(我的目标,fwiw,是能够引用具有不同返回类型和大量字符串参数的众多方法。我甚至不想打电话给它们 - 我只是想反思它们的属性。我做比如lambda的安全性,而不仅仅是键入方法名称字符串。)


修改:澄清我想要使用Action<string>的原因:我的示例中的int可能是多种类型中的任何一种。我试着模仿那种类型 -

void Set<T>(Func<Foo, Func<string, T>> a) { }
void Test() { Set(foo => foo.Hello); }  // fails

- 但是编译器无法派生T(大概是因为我不能在返回类型上重载?)。

还有其他想法吗?只要我能让编译器检查该方法组的名称,我就不会反对这种疯狂的反思。

2 个答案:

答案 0 :(得分:7)

如果它具有非void返回类型,则它不再与Action<string>兼容。换句话说,这也会失败:

int Foo(string s) { return 10; }

// Error: wrong return type
Action<string> action = new Action<string>(Foo);

由于为什么这是不允许的原因,请参阅Eric Lippert关于"The void is invariant"的博文。

您应该能够使用这样的方法组语法:

public class Foo { public int Hello(string s) { return 10; } }

void Test()
{
    Func<Foo, Func<string, int>> a = foo => foo.Hello;
}

在VS2008和VS2010中都适合我。对C#4的方法组转换和类型推断进行了一些更改 - 不幸的是,细节让我感到惊讶 - 但我不相信这种情况会受到这些更改的影响。

答案 1 :(得分:6)

使用void返回类型,foo.Hello是Action<string>。使用int返回类型,它现在是Func<string, int>

要处理多个返回类型 - 并假设您不需要对返回值执行任何操作 - 您可以轻松地包装非void函数:

Func<Foo, Action<string>> a = foo => s => foo.Hello(s);