Pio*_*fer 17 c# generics type-inference
请考虑以下示例:
class Test
{
public void Fun<T>(Func<T, T> f)
{
}
public string Fun2(string test)
{
return "";
}
public Test()
{
Fun<string>(Fun2);
}
}
Run Code Online (Sandbox Code Playgroud)
编译好.
我想知道为什么我不能删除<string>泛型参数?我收到一个错误,无法从使用中推断出来.
我知道这样的推断对于编译器来说可能是一个挑战,但是它似乎是可能的.
我想解释一下这种行为.
编辑回答Jon Hanna的回答:
那么为什么会这样呢?
class Test
{
public void Fun<T1, T2>(T1 a, Func<T1, T2> f)
{
}
public string Fun2(int test)
{
return test.ToString();
}
public Test()
{
Fun(0, Fun2);
}
}
Run Code Online (Sandbox Code Playgroud)
在这里我只绑定一个参数T1 a,但T2似乎同样困难.
Jon*_*nna 13
它无法推断类型,因为此处未定义类型.
Fun2不是Func<string, string>,它是可以分配的东西Func<string, string>.
所以如果你使用:
public Test()
{
Func<string, string> del = Fun2;
Fun(del);
}
Run Code Online (Sandbox Code Playgroud)
要么:
public Test()
{
Fun((Func<string, string>)Fun2);
}
Run Code Online (Sandbox Code Playgroud)
然后,您明确地创建了一个Func<string, string>from Fun2,并且泛型类型推断也相应地起作用.
相反,当你这样做时:
public Test()
{
Fun<string>(Fun2);
}
Run Code Online (Sandbox Code Playgroud)
然后,重载集Fun<string>只包含一个接受a Func<string, string>的编译器,编译器可以推断出你想要使用Fun2它.
但是你要求它根据参数的类型推断泛型类型,以及基于泛型类型的参数类型.这比其中任何一种类型的推断都要大.
(值得考虑的是,在.NET 1.0中,委托不仅不是通用的 - 所以你必须定义delgate string MyDelegate(string test)- 但是也必须使用构造函数创建对象Fun(new MyDelegate(Fun2)).语法已经改变,以便在几个方面更容易地使用委托,但隐含使用Fun2as Func<string, string>仍然是幕后的委托对象的构造).
那么为什么会这样呢?
class Test
{
public void Fun<T1, T2>(T1 a, Func<T1, T2> f)
{
}
public string Fun2(int test)
{
return test.ToString();
}
public Test()
{
Fun(0, Fun2);
}
}
Run Code Online (Sandbox Code Playgroud)
因为它可以推断,按顺序:
T1是int.Fun2被分配给Func<int, T2>一些人T2.Fun2可以分配给一Func<int, T2>如果T2是string.因此T2是字符串.特别是,Func一旦有了参数类型,就可以从函数中推断出返回类型.这也是一样的(并且值得编译器付出努力),因为它在Linq中很重要Select.这带来了一个相关的案例,事实上x.Select(i => i.ToString())我们没有足够的信息来知道lambda被强制转换为什么.一旦我们知道x是IEnumerable<T>或IQueryable<T>我们知道我们是否拥有Func<T, ?>或Expression<Func<T, ?>>其余的可以从那里推断出来.
这里也值得注意的是,推断返回类型并不会导致推断其他类型的歧义.考虑一下我们是否同时拥有你的Fun2(拿一个string和拿一个的那个int).这是有效的C#超载,反而使得类型的扣除Func<T, string>是Fun2可以转换几乎是不可能的; 两者都有效.
但是,虽然.NET确实允许在返回类型上重载,但C#没有.因此,Func<T, TResult>一旦T确定了类型,就没有有效的C#程序对从方法(或lambda)创建的返回类型不明确.相对容易,再加上非常实用,使得编译器可以为我们推断.
| 归档时间: |
|
| 查看次数: |
497 次 |
| 最近记录: |