Suppose I have a class:
class MyClass {
public int MyMethod(Func<int, int> f) { return 0; }
public int MyMethod(Expression<Func<int, int>> f) { return 1; }
}
When I try to call the method with a lambda expression, I get a compile error stating that the call is ambiguous between the two overloads:
var myClass = new MyClass();
myClass.MyMethod(x => 1 + x); // Error!
while, of course, calling with an explicit type works fine:
myClass.MyMethod((Func<int, int>)(x => 1 + x)); // OK, returns 0
myClass.MyMethod((Expression<Func<int, int>>)(x => 1 + x)); // OK, returns 1
The expression tree contains more information (the actual code), and I may want to make use of this information when it is available. But I also want my code to work with delegates. Unfortunately, this ambiguity makes it so I have to find another way to distinguish between the two calls, which messes up an otherwise clean API.
The C# spec doesn't say anything about this specific situation, so in this sense the behavior does match the spec.
However, there is an argument to be made that the expression tree should be preferred over the delegate. The Compile
method acts as an explicit conversion from an expression tree to a delegate. The expression tree contains more information, and when you compile to a delegate, you lose that information. There is no conversion in the other direction.
Are there any reasons not to prefer the expression tree?