泛型不能推断第二个参数? [英] Generics can't infer second parameter?

查看:100
本文介绍了泛型不能推断第二个参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到C#编译器并不推断第二个泛型参数。

示例:

C ++模板代码:(yea I知道模板不能像泛型一样工作)

  class Test {
public:
template< T类,V类>
T test(V v){
//用v
做某事return T();
}
};

int i = 0;
Test t = new Test();
double j = t.test< double>(i); //推断V为int

模板(和泛型)不能推断返回类型,所以在C ++我给它第一个模板参数,第二个模板参数是从变量类型推断的。



现在,C#中的示例:

  class Test {
public T test< T,V>(V v)其中T:new(){
// do用v
返回新的T();
}
};

int i = 0;
Test t = new Test();
double j = t.test< double>(i); //错误使用泛型方法'Test.test< T,V>(V)'需要'2'类型参数

但是,如果我使用1类型,我不必显式指定类型:

  class Test { 
public V test< V>(V v)其中V:new(){
return new V();
}
};

int i = 0;
Test t = new Test();
int j = t.test(i); // OK推断V为int。

所以,为什么不能推断第二种类型在c ++模板中,它显然可以)?

我确定它是按照这种方式设计的(我怀疑他们是.Net团队忽略了这一点),所以为什么是这样设计的我必须明确指定两种类型?



编辑:



从目前为止的答案中,这两种语言都支持通过模板参数的数量进行重载。



所以,为什么是C#用这种方式设计的?语言实现中有什么不同,不允许显式声明一个参数?

解决方案


$被设计为一种比C ++更轻微的大脑弯曲语言。 b $ b

特别是,我认为将C#泛型与C ++模板进行比较并不是一个好主意 - 出于各种原因,它们基本上是两种非常不同的方法来完成类似的 一些情况。 C ++方法在某些方面肯定是灵活的 - 尽管它不允许(据我了解)只存在于二进制形式的模板,或者在执行时创建新的模板特化。基本上C ++模板化方法并不适合.NET的其他部分。



现在至于为什么你不能指定某些 em>类型参数并允许其他人被推断出来(这是一个语言决定而不是平台决定;我相信就.NET本身而言它是可行的关心) - 我再次相信这是为了简单起见。选择正确的方法正确的类型参数在C#中已经非常复杂 - 比大多数C#开发人员更容易掌握。它包含:


  • 潜在地考虑目标的编译时类型中的类型层次结构的方法
  • 通过参数数量重载

  • 通过类型参数的数量重载
  • 命名参数的作用
  • li>
  • 可选参数的影响

  • 通用类型参数约束对参数类型(由目标方法指定的 not 约束) ,note)

  • 为委托转换的方法组
  • 匿名函数转换

  • 为类型参数输入推断

  • 动态分类

  • 泛型协方差和反变换


    就我个人而言,我认为这足以让我的头脑得到满足,而不会允许更多的可能性,M仍然可以成为候选人,如果它至少 类型参数。你是否也想要命名的类型参数和可选的类型参数? ;)



    我仔细研究了超载,遵循规范等等。我发现了一些让语言设计师挠头并尝试工作的地方编译器应该做什么。我发现编译器肯定会出错的地方。



    所以是的,它基本上是为了简单起见,有时这是一种痛苦 - 但通常你可以解决它。对于每个潜在的功能,您需要考虑:


    • 功能对于开发人员的好处

    • 开发人员花费时间理解开发人员的功能成本

    • 语言设计师在设计和彻底指定开发方面的成本

    • 编译器编写者正确实施它的成本

    • 测试团队对其进行彻底测试的成本(与其他所有内容相结合)

    • 未来潜在特性的成本(如果这样会使语言更加复杂,那么为其他特性留下更少的潜在可能额外的复杂性)

      I've noticed that the C# compiler doesn't infer second generic parameter.
      Example:

      C++ template code: (yea I know that templates don't work like generics)

      class Test {
      public:
      template <class T,class V> 
          T test(V v) {
             //do something with v
             return T();
          }
      };
      
      int i = 0;
      Test t = new Test();
      double j = t.test<double>(i); //infers V as int
      

      The templates (and generics) can't infer return type, so in C++ I give it the first template parameter, and the second template parameter is inferred from the variable type.

      Now, same example in 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
      

      But if i use 1 type, I don't have to explicitly specify the type:

      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.
      

      So, why can't C# generics infer the second type (while in c++ templates it clearly can) ?
      I'm sure it's designed that way (I doubt they the .Net team overlooked this), so why is it designed this way that I must explicitly specify both types?

      Edit:

      From the discussions we had in the answers so far, both languages support overloading by number of template parameters.

      So again, why is C# designed this way ? What's different in the language implementation that doesn't allow to explicitly declare only one parameter ?

      解决方案

      C# has been designed to be a slightly less brain-bending language than C++.

      In particular, I don't think it's a great idea to compare C# generics to C++ templates for various reasons - they're fundamentally two really quite different approaches to accomplishing similar things in some situations. The C++ approach is certainly flexible in some ways - although it doesn't allow (as I understand it) templates which only exist in binary form, or new template specializations to be created at execution time. Basically the C++ templating approach doesn't sit well with the rest of how .NET fits together.

      Now as for why you can't specify some type arguments and allow others to be inferred (which is a language decision rather than a platform decision; I'm sure it would be feasible as far as .NET itself is concerned) - again, I believe this is for the sake of simplicity. Choosing the exact right method and the right type arguments is already extremely complicated in C# - more complicated than most C# developers can get their heads round. It involves:

      • Potentially considering methods up the type hierarchy from the compile-time type of the target
      • Overloading by number of parameters
      • Overloading by the number of type parameters
      • The effect of named arguments
      • The effect of optional parameters
      • The effect of generic type parameter constraints on parameter types (not constraints specified by the target method, note)
      • Method group to delegate conversions
      • Anonymous function conversions
      • Type inference for type arguments
      • Dynamic typing
      • Generic covariance and contravariance

      Personally, I think that's enough to get my head around, without allowing yet more possiblities via "M can still be a candidate if it has at least as many type parameters as specified type arguments". Would you also want named type arguments and optional type parameters? ;)

      I've looked at overloading quite a lot, following the spec thoroughly etc. I've found areas which make the language designers scratch their heads and try to work out what the compiler should do. I've found areas which the compiler definitely gets wrong. I wouldn't want to add any more complexity here without a really good reason.

      So yes, it's basically for the sake of simplicity, and sometimes that's a pain - but often you can work around it. For every potential feature, you need to consider:

      • The benefit of the feature to end developers
      • The cost of the feature to end developers in terms of time spent understanding it
      • The cost to the language designers in designing and specifying it thoroughly
      • The cost to the compiler writers in implementing it correctly
      • The cost to the test team in testing it thoroughly (in conjunction with everything else around overloading)
      • The cost to future potential features (if this one makes the language more complicated, that leaves less "potentially grokable" additional complexity for other features)

      这篇关于泛型不能推断第二个参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆