I have the following code:
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
However, the following does not compile:
var comparer = delegate(string value) {
return value != "0";
};
Why can't the compiler figure out it is a Func<string, bool>
? It takes one string parameter, and returns a boolean. Instead, it gives me the error:
Cannot assign anonymous method to an implicitly-typed local variable.
I have one guess and that is if the var version compiled, it would lack consistency if I had the following:
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
The above wouldn't make sense since Func<> allows only up to 4 arguments (in .NET 3.5, which is what I am using). Perhaps someone could clarify the problem. Thanks.
Different delegates are considered different types. e.g.,
Action
is different thanMethodInvoker
, and an instance ofAction
can't be assigned to a variable of typeMethodInvoker
.So, given an anonymous delegate (or lambda) like
() => {}
, is it anAction
or aMethodInvoker
? The compiler can't tell.Similarly, if I declare a delegate type taking a
string
argument and returning abool
, how would the compiler know you really wanted aFunc<string, bool>
instead of my delegate type? It can't infer the delegate type.Others have already pointed out that there are infinitely many possible delegate types that you could have meant; what is so special about
Func
that it deserves to be the default instead ofPredicate
orAction
or any other possibility? And, for lambdas, why is it obvious that the intention is to choose the delegate form, rather than the expression tree form?But we could say that
Func
is special, and that the inferred type of a lambda or anonymous method is Func of something. We'd still have all kinds of problems. What types would you like to be inferred for the following cases?There is no
Func<T>
type that takes a ref anything.We don't know the type of the formal parameter, though we do know the return. (Or do we? Is the return int? long? short? byte?)
We don't know the return type, but it can't be void. The return type could be any reference type or any nullable value type.
Again, we don't know the return type, and this time it can be void.
Is that intended to be a void-returning statement lambda or something that returns the value that was assigned to q? Both are legal; which should we choose?
Now, you might say, well, just don't support any of those features. Just support "normal" cases where the types can be worked out. That doesn't help. How does that make my life easier? If the feature works sometimes and fails sometimes then I still have to write the code to detect all of those failure situations and give a meaningful error message for each. We still have to specify all that behaviour, document it, write tests for it, and so on. This is a very expensive feature that saves the user maybe half a dozen keystrokes. We have better ways to add value to the language than spending a lot of time writing test cases for a feature that doesn't work half the time and doesn't provide hardly any benefit in cases where it does work.
The situation where it is actually useful is:
because there is no "speakable" type for that thing. But we have this problem all the time, and we just use method type inference to deduce the type:
and now method type inference works out what the func type is.
Eric Lippert has an old post about it where he says
My post doesn't answer the actual question, but it does answer the underlying question of :
"How do I avoid having to type out some fugly type like
Func<string, string, int, CustomInputType, bool, ReturnType>
?" [1]Being the lazy/hacky programmer that I am, I experimented with using
Func<dynamic, object>
- which takes a single input parameter and returns an object.For multiple arguments, you can use it like so:
Tip: You can use
Action<dynamic>
if you don't need to return an object.Yeah I know it probably goes against your programming principles, but this makes sense to me and probably some Python coders.
I'm pretty novice at delegates... just wanted to share what I learned.
[1] This assumes that you aren't calling a method that requires a predefined
Func
as a parameter, in which case, you'll have to type that fugly string :/Only Eric Lippert knows for sure, but I think it's because the signature of the delegate type doesn't uniquely determine the type.
Consider your example:
Here are two possible inferences for what the
var
should be:Which one should the compiler infer? There's no good reason to choose one or the other. And although a
Predicate<T>
is functionally equivalent to aFunc<T, bool>
, they are still different types at the level of the .NET type system. The compiler therefore cannot unambiguously resolve the delegate type, and must fail the type inference.The following points are from the MSDN regarding Implicitly Typed Local Variables:
MSDN Reference: Implicitly Typed Local Variables
Considering the following regarding Anonymous Methods:
MSDN Reference: Anonymous Methods
I would suspect that since the anonymous method may actually have different method signatures, the compiler is unable to properly infer what the most appropriate type to assign would be.