I suppose someone from the C# team can give a much better answer but I try my shot. Question here is not if it's a best practice or not but if it's possible and, if not, why.
Let's start with what you would write:
var i = (x => x)(42);
Pretty straightforward, you pass an integer (42
) to a lambda, it plays with it and it returns the same value. Its parameter is an integer (inferred from its usage), it returns an integer (inferred from the expression) and i
is another integer (inferred from return value).
Unfortunately this is broken in the very first step. Let me cite big Jon:
Compiler tries to work out the types of the parameters for lambda expressions based on the context in which it's used.
What does it mean? Actually that the compiler need some information but it can use only:
- An explicit cast, constructor or declaration like in
(Func<int, int>)(x => x))
ornew Func<int, int>(x => x)
. Required types here are given or inferred using the required final type. - An assignment (again because the final type can be inferred) like in:
Func<int, int> f = (x => x);
In your case the compiler have to infer function type from its parameters and it's not possible because parameters are validated against the expression and not vice-versa.
Why this is not possible in C#? Because (x => x)
is just a delegate then it can be any delegate that accept an integer parameter (if we suppose the compiler can infer lhs from rhs and validate rhs according to lhs) and returns another integer. Actually conversion between delegates are not allowed in C# so the expression is invalid (even if this special delegate won't be assigned to any variable and it won't be used in the future). It could be Func<int, int>
or Expression<Func<int, int>>
or any other delegate (for bool
parameter it may even bee Predicate<bool>
).
Of course this is a C# design decision, the same expression - for example - in VB.NET is perfectly valid:
Dim i = (Function(x) x)(42)
Different language, different rules to obey, C# goal is to avoid this kind of ambiguity.