Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I define a method to accept EITHER a Func<T> OR an Expression<Func<T>>?

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.

like image 845
Dan Tao Avatar asked Oct 21 '10 19:10

Dan Tao


People also ask

What is expression method C#?

An expression-bodied method consists of a single expression that returns a value whose type matches the method's return type, or, for methods that return void , that performs some operation.

What is expression in Linq?

LINQ introduced the new type called Expression that represents strongly typed lambda expression. It means lambda expression can also be assigned to Expression<TDelegate> type. The . NET compiler converts the lambda expression which is assigned to Expression<TDelegate> into an Expression tree instead of executable code.


2 Answers

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.

like image 109
Samuel Neff Avatar answered Sep 23 '22 22:09

Samuel Neff


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.

like image 27
Paw Baltzersen Avatar answered Sep 24 '22 22:09

Paw Baltzersen