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

2

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.

Nude answered 21/10, 2010 at 19:55 Comment(3)
Why is the title using VB syntax and the rest of the question using C# syntax?Sherlocke
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.Bruner
@klausbyskov: I... don't know. I will change it.Nude
A
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.

Amadoamador answered 21/10, 2010 at 20:1 Comment(1)
Gah, yeah... I just thought of that myself. You're right, but... I hate it!Nude
R
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.

Rabiah answered 21/10, 2010 at 20:15 Comment(1)
Whoa... haha, strange idea. Interesting, at least ;)Nude

© 2022 - 2024 — McMap. All rights reserved.