Why cannot C# compiler implicitly infer `Foo foo = (int x) => x.ToString();` for the delegate type `static delegate R Foo<I, R>(I i);`?
class Program
{
static delegate R Foo<I, R>(I i);
static void Main(string[] a开发者_开发知识库rgs)
{
Foo<int, string> foo = (int x) => x.ToString();
// Why can't the compiler IMPLICITLY infer the following declaration?
//Foo foo = (int x) => x.ToString();
}
}
EDIT 1: The code above is not compilable actually. The delegate I defined has static modifier that is not applicable!
This isn't about type inference, it's because there's no such type as Foo
. (Foo<I,R>
and Foo
, if it existed, are two completely different types as far as the compiler is concerned.)
For the same reason you can't legally do any of the following:
Dictionary d = new Dictionary<int, string>();
List l = new List<string>();
Func f = new Func<int, string>(i => i.ToString());
Because Foo is not a type that has been defined, but Foo<,> is a type that has been defined.
*Removed var
suggestion as it doesn't work...
C# spec states that lambdas are untyped constructs (like method groups). They can be converted to compatible types. For this reason, you can't write var something = (SomeType a) => a;
The rationale is they can be interpreted as expression trees and delegates depending on the context. There's no way to know which one is your intent outside a specific context. You cannot use a lambda expression or method group outside a context in which they can be converted to something.
C# Language Specification v4.0 (§1.4.12)
Anonymous function conversions and method group conversions
Anonymous functions and method groups do not have types in and of themselves, but may be implicitly converted to delegate types or expression tree types. Anonymous function conversions are described in more detail in §1.44 and method group conversions in §1.45.
Because there is no such type Foo
. If declaring a variable of a certain type, you have to define its generic parameters as well.
In example, this works fine:
F((int x) => x.ToString());
private static void F<I,R>(Foo<I, R> foo)
{
}
You could make a small wrapper class.
static class Foo {
public static Foo<I, R> Create<I, R>(Foo<I, R> foo) {
return foo;
}
}
Then this works fine:
var foo = Foo.Create((int x) => x.ToString());
精彩评论