3

我正在尝试在 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;
}

但是,当我将返回类型更改为Helloint,我得到

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

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

有任何想法吗?

(我的目标,fwiw,是能够引用具有不同返回类型和大量字符串参数的众多方法。我什至不打算调用它们 - 我只是想反映它们的属性。我确实喜欢安全然而,与只输入方法名称字符串相比,lambdas。)


编辑:澄清我想要使用的原因Action<string>int在我的示例中可能是多种类型中的任何一种。我尝试模板化该类型——

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

- 但是编译器不能派生T(大概是出于同样的原因,我不能在返回类型上重载?)。

还有其他想法吗?在这种情况下,只要我能让编译器检查该方法组的名称,我并不反对一些疯狂的反思。

4

2 回答 2

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 的方法组转换和类型推断发生了一些变化——不幸的是,细节让我无法理解——但我不相信这种情况会受到这些变化的影响。

于 2010-10-22T10:14:29.803 回答
6

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

要处理多种返回类型——假设你不需要对返回值做任何事情——你可以简单地包装非 void 函数:

Func<Foo, Action<string>> a = foo => s => foo.Hello(s);
于 2010-10-22T10:15:25.403 回答