Reputation: 13419
I'm trying to use a method group in a lambda expression, like this:
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;
}
When I change the return type of Hello
to int
, however, I get
'Bar.Hello(string)' has the wrong return type.
I've tried playing around with Func
in place of Action
, but that seems to prevent me from using the method group syntax.
Any ideas?
(My goal, fwiw, is to be able to refer to numerous methods that have different return types and lots of string arguments. I don't even intend to call them - I just want to reflect over their attributes. I do like the safety of lambdas, however, versus just typing in method name strings.)
Edit: to clarify my reasons for wanting to use Action<string>
: int
in my example may be any of a number of types. I tried templating that type --
void Set<T>(Func<Foo, Func<string, T>> a) { }
void Test() { Set(foo => foo.Hello); } // fails
-- but the compiler can't derive T
(presumably for the same reasons I can't overload on return type?).
Any other ideas? I'm not opposed in this case to some crazy reflection as long as I can get the compiler to check the name of that method group.
Upvotes: 3
Views: 1538
Reputation: 1499770
When it has a non-void return type, it's no longer compatible with Action<string>
. In other words, this would fail too:
int Foo(string s) { return 10; }
// Error: wrong return type
Action<string> action = new Action<string>(Foo);
For the reasons why this isn't allowed, see Eric Lippert's blog post on "The void is invariant".
You should be able to use method group syntax like this:
public class Foo { public int Hello(string s) { return 10; } }
void Test()
{
Func<Foo, Func<string, int>> a = foo => foo.Hello;
}
That works for me in both VS2008 and VS2010. There have been some changes to method group conversions and type inference for C# 4 - the details escape me unfortunately - but I don't believe this case is affected by those changes.
Upvotes: 7
Reputation: 185852
With a void return type, foo.Hello is an Action<string>
. With an int return type, it's now a Func<string, int>
.
To handle multiple return types — and assuming you don't need to do anything with the return value — you can trivially wrap non-void functions thus:
Func<Foo, Action<string>> a = foo => s => foo.Hello(s);
Upvotes: 6