Can I define a method to accept EITHER a Func<T> OR an Expression<Func<T>>?
-
10-10-2019 - |
Question
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.
Solution
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.
OTHER TIPS
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.