7

If I attempt to write two overloads of a method, one accepting an Expression<Func<T>> parameter and another accepting a Func<T>, I will get a compiler error on trying to call the method with a lambda expression because the two signatures create ambiguity. The following would be problematic, for example:

Method(() => "Hello"); // Is that a Func<string>,
                       // or is it an Expression<Func<string>>?

I get that. But I don't like the approach of just accepting an Expression<Func<string>>, as this forces calling code to use a lambda expression. What if I want to be able to accept a method group as well?

My basis for asking this question is that I'm working on some code where I'd like to be able to write something like this:

Method(() => "Hello");

...and get output like this:

Executed '() => "Hello"' and got "Hello" back.

Meanwhile, I'd like to be able to do this as well:

Method(ReturnHello);

...and get output like this:

Executed 'ReturnHello' and got "Hello" back.

Is there any way to do what I'm trying to do here, without just using two different method names (e.g., ExpressionMethod and FuncMethod)? I realize that wouldn't be such a big deal; I'm just curious if there's another way.

Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • 1
    Why is the title using VB syntax and the rest of the question using C# syntax? – Klaus Byskov Pedersen Oct 21 '10 at 19:58
  • I think you'd have to use reflection to determine whether or not the passed delegate is a lambda expression or a function. But I think any code you write shouldn't change behaviour between the two; that seems like a nasty code smell to me. – Reinderien Oct 21 '10 at 19:58
  • @klausbyskov: I... don't know. I will change it. – Dan Tao Oct 21 '10 at 20:01

2 Answers2

1

You can overload a method to take either a Func<T> or Expression<Func<T>> but when you do that the automatic type determination fails so you need to explicitly define the types via casting. Like this:

public static void Test()
{
    Test((Func<string>)(() => "helllo"));
    Test((Expression<Func<string>>) (() => "hello"));
}

public static void Test<T>(Func<T> func)
{

}

public static void Test<T>(Expression<Func<T>> expression)
{

}

It's not pretty.

Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
1

Maybe make one method with two named parameters with default values of null.

public static void Test<T>(Func<T> func = null, Expression<Func<T>> expression = null)
{
}

I know you miss the OR in this, but that's easy to check for in the method.

Paw Baltzersen
  • 2,662
  • 3
  • 24
  • 33