C# 仿制药可以';我们不能推断第二个参数吗?
我注意到C#编译器不会推断第二个泛型参数。C# 仿制药可以';我们不能推断第二个参数吗?,c#,.net,templates,generics,C#,.net,Templates,Generics,我注意到C#编译器不会推断第二个泛型参数。 例如: C++模板代码:(是的,我知道模板不像泛型那样工作) 类测试{ 公众: 模板 T检验(V){ //用v做点什么 返回T(); } }; int i=0; 测试t=新测试(); 双j=t检验(i)//推断V为int 模板(和泛型)不能推断返回类型,所以在C++中,我给它第一个模板参数,第二个模板参数是从变量类型推断出来的。 现在,C#中的相同示例: 类测试{ 公共T检验(V),其中T:new(){ //用v做点什么 返回新的T(); } };
例如: C++模板代码:(是的,我知道模板不像泛型那样工作)
类测试{
公众:
模板
T检验(V){
//用v做点什么
返回T();
}
};
int i=0;
测试t=新测试();
双j=t检验(i)//推断V为int
模板(和泛型)不能推断返回类型,所以在C++中,我给它第一个模板参数,第二个模板参数是从变量类型推断出来的。 现在,C#中的相同示例:
类测试{
公共T检验(V),其中T:new(){
//用v做点什么
返回新的T();
}
};
int i=0;
测试t=新测试();
双j=t检验(i)//使用泛型方法“Test.Test(V)”时出错需要“2”类型参数
但如果使用1类型,则不必显式指定类型:
class Test {
public V test<V>(V v) where V: new() {
return new V();
}
};
int i = 0;
Test t = new Test();
int j = t.test(i); //OK infers V as int.
类测试{
公共V测试(V),其中V:new(){
返回新的V();
}
};
int i=0;
测试t=新测试();
int j=t.试验(i)//OK推断V为int。
< > >强>为什么不能推断第二类(而C++模板中可以清楚地)?
我确信它是这样设计的(我怀疑.Net团队忽略了这一点),所以为什么它是这样设计的,我必须明确指定这两种类型
编辑:
从到目前为止我们在答案中的讨论来看,两种语言都支持通过模板参数的数量进行重载
那么,为什么C#是这样设计的呢?不允许只显式声明一个参数的语言实现有什么不同 正如Dan所说,C#不允许您仅推断泛型参数集的某些类型参数。这可能会根据泛型参数的数量启用重载(C#允许,至少对于泛型类是如此)
但是,您可以指定泛型类的参数,并推断该类中泛型方法的参数。但是这种解决方法并不总是一个好的解决方案。< P> C被设计成比C++略微少的脑弯曲语言。
特别是,我认为把C泛型与C++模板进行比较是不太好的。因为它们在很多情况下都是两种非常不同的方法来完成类似的事情。C++方法在某些方面当然是灵活的,尽管它不允许(我理解)只存在二进制形式的模板,或者在执行时创建的新模板专长。基本上,C++模板方法与其他.NET如何组合在一起并不合适。
现在,关于为什么不能指定某些类型参数并允许推断其他类型参数(这是一个语言决策,而不是平台决策;我相信就.NET本身而言,这是可行的)——同样,我认为这是为了简单。在C#中,选择完全正确的方法和正确的类型参数已经非常复杂了——比大多数C#开发人员所能理解的还要复杂。它涉及:
- 可能会考虑从目标的编译时类型向上扩展类型层次结构的方法
- 按参数数重载
- 按类型参数的数量重载
- 命名参数的效果
- 可选参数的影响
- 泛型类型参数约束对参数类型的影响(注意,不是目标方法指定的约束)
- 方法组到委托的转换
- 匿名函数转换
- 类型参数的类型推断
- 动态类型
- 广义协方差与逆变换
- 该功能对终端开发人员的好处
- 就理解该特性所花费的时间而言,该特性对最终开发人员的成本
- 语言设计者在设计和详细说明它时所付出的代价
- 编译器编写者正确实现它的成本
- 测试团队彻底测试它的成本(与过载相关的所有其他因素一起)
- 未来潜在功能的成本(如果这一功能使语言更加复杂,那么其他功能的“潜在可探索性”增加的复杂性就会降低)
class Test {
public T test<T,V>(V v) where T: new() {
//do something with v
return new T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //Error Using the generic method 'Test.test<T,V>(V)' requires '2' type arguments
class Test {
public V test<V>(V v) where V: new() {
return new V();
}
};
int i = 0;
Test t = new Test();
int j = t.test(i); //OK infers V as int.
NewAction = ActionOf(Of FooType, BarType).NewAction(AddressOf MyFunctionOfBozFooBar, someBoz)