1

I'm looking to get hold of a method name from a lambda expression, I'm aware it can be done this way:

GetName(() => MethodA());

My issue is that if MethodA takes any args, you have to supply them just to satisfy the compiler about the expression (after all, how can it know you're not actually executing it?)

I'd like to be able to do:

GetName(() => MethodA);

Is there a way of doing this?


NOTE: This is not a duplicate, this is dealing with a Method Group and not an actual "invocation" of a method.

Clint
  • 6,133
  • 2
  • 27
  • 48
  • 2
    @Rawling this isn't a duplicate! That question involves a call to the method in question. – Clint Aug 07 '14 at 14:59
  • Indeed, this is not a duplicate. I voted to reopen it, 4 more votes left, shouldn't take too long hopefully. As for your question, I'm afraid the answer is *no*. – Lucas Trzesniewski Aug 07 '14 at 15:01
  • @LucasTrzesniewski I'm afraid it's looking as if it isn't possible, which is a shame. Essentially I'm using it to determine if a method is overridden in a derived class - I'm aware this is a bad idea, I'm doing it just to play around and hack something together quickly to be redone later. – Clint Aug 07 '14 at 15:05
  • @Clint My bad, how about [this one](http://stackoverflow.com/questions/8225302/get-the-name-of-a-method-using-an-expression)? (Question looks similar, not sure if answers will help.) – Rawling Aug 07 '14 at 15:10
  • you say 'I'm looking to get hold of a method name from a lambda expression' but go on to say you don't want to have to _specify_ a valid lambda, thus you seem to be saying you want to be able to write: GetName(MethodA); and I guess I'm asking 'how you don't already know it' (ie if MethodA is a Method Group and not a delegate how can you 'get hold of' or pass one around, if it is a delegate you can already GetName(delegate)) - I think some info is missing. – tolanj Aug 07 '14 at 15:39

2 Answers2

3

Certainly. If you have your GetName method take an Expression<Func<Action>> as a parameter, for example, then you can pass () => MethodA into it, as long as MethodA is convertible to the same delegate signature as Action.

void Main()
{
    Expression<Func<Action>> x = () => Foo;
    Expression<Func<Func<int>>> y = () => Foo2;
    var xName = ((MethodInfo)((ConstantExpression)((MethodCallExpression)((UnaryExpression)x.Body).Operand).Object).Value).Name;
}

void Foo(){}
int Foo2(){return 0;}

You can write your GetName method to examine the given expression and extract out the name of the method group from it. However, there are two things you should keep in mind.

  1. Even if your lambda expression appears to "call" a method, it's only an expression and won't actually generate a call to that method.
  2. Trying to capture a method group this way will make it very difficult to distinguish between overloaded methods with the same name.

For that reason, I have to imagine you'd be better off using a more traditional approach that does involve a method call expression.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Pretty useful that it works so long as it matches the signature, only problem is I'd have to write n number of methods to match the possibilities of signatures being used... – Clint Aug 07 '14 at 17:04
  • @Clint: Exactly. Mind if I ask why you're trying to avoid method-call syntax? – StriplingWarrior Aug 07 '14 at 18:15
1

For the case, of a void-returning parameterless method, the signature of GetName could look like this:

string GetName(Expression<Func<Action>> methodExpression)

That Action in there is a problem, to make it work for methods with other signatures, you would need to add lots of overloads for other delegate types.

A solution to this is to make GetName generic and let the user specify the delegate type:

string GetName<T>(Expression<Func<T>> methodExpression)

…

GetName<Action>(() => MethodA)

The problem with this approach is that T can be any type, not just a delegate, so it's very easy to call this version of GetName incorrectly, especially since GetName(() => MethodB()) will often compile (specifically, when MethodB returns something), due to type inference.

And type constrains won't help you here, you can't write where T : Delegate.

svick
  • 236,525
  • 50
  • 385
  • 514