type arguments can't be inferred from the usage for higher-order function
Asked Answered
B

2

10

I have the following higher-order function:

public static Func<T, bool> Not<T>(Func<T, bool> otherFunc)
{
    return arg => !otherFunc(arg);
}

And trying to call it like that:

var isValidStr = LinqUtils.Not(string.IsNullOrWhiteSpace);

Compiler gives me "type arguments cannot be inferred from the usage" error. But the following works:

var isValidStr = LinqUtils.Not((string s) => string.IsNullOrWhiteSpace(s));

I wonder what the difference is? string.IsNullOrWhiteSpace is already a non-overloaded function with the exactly same signature.

As mentioned in comments, the following also works and still doesn't explain why type inference fails in this case:

var isValidStr = LinqUtils.Not<string>(string.IsNullOrWhiteSpace);
Betteann answered 12/6, 2012 at 17:24 Comment(2)
possible duplicate of C# 3.0 generic type inference - passing a delegate as a function parameterEma
IsNullOrWhiteSpace is a method group. The method group only has one participating member today, but it could get more in the future.Ema
C
6

The details of the issue you are dealing with are answered by Eric Lippert on his blog, here.

Basically, as "David B" said in your comments, "IsNullOrWhiteSpace is a method group. The method group only has one participating member today, but it could get more in the future."

Capillaceous answered 12/6, 2012 at 17:37 Comment(5)
Awesome link. Wouuld the proposed code would work in c# 4.0 ? var isValidStr = LinqUtils.Not(string.IsNullOrWhiteSpace);Ema
No, the upgrade to type inference improvement only works for the return type.Capillaceous
No, it doesn't seem to work in C# 4.0 :( Also, s => string.IsNullOrWhiteSpace(s) doesn't work either making me think that "method group" explanation is not valid.Betteann
what? I didn't say it would work. We are saying the exact opposite. We are saying, type inference CANNOT work on parameters as method groups at all in 3.0, and only works on return types in 4.0. Your question is precisely what Eric is talking about on his blog.Capillaceous
Your s => string.IsNullOrEmpty(s) does not change the answer to your question. In this case, the s is still generic, and cannot be inferred. This example deals with a bit more complex situation about recursive type inference in lambdas. I can look for the link if you would like it.Capillaceous
C
2

This works:

var isValidStr = Not<string>(string.IsNullOrWhiteSpace);

Although, It seems like the compiler should have enough information to infer the type parameters here - and this shouldn't be required...

Chyou answered 12/6, 2012 at 17:26 Comment(1)
I know. It's essentially the same as my second part. I wonder why type inference doesn't work.Betteann

© 2022 - 2024 — McMap. All rights reserved.