为什么C#构造函数不能推断类型?

时间:2010-08-25 21:02:24

标签: c# generics constructor type-inference

为什么构造函数不支持类型推断,就像通用方法一样?

public class MyType<T>
{
   private readonly T field;
   public MyType(T value) { field = value; }
}

var obj = new MyType(42); // why can't type inference work out that I want a MyType<int>?

虽然你可以通过工厂类来解决这个问题,

public class MyTypeFactory
{
   public static MyType<T> Create<T>(T value)
   {
      return new MyType<T>(value);
   }
}
var myObj = MyTypeFactory.Create(42);

构造函数不支持类型推断是否存在实际或哲学原因?

5 个答案:

答案 0 :(得分:121)

  

构造函数不支持类型推断是否存在哲学原因?

没有。当你有

new Foo(bar)

然后我们可以在范围内识别所有称为Foo的类型,而不管通用arity,然后使用修改的方法类型推断算法对每个类型执行重载解析。然后,我们必须创建一个“更好”算法,该算法确定两个具有相同名称但不同通用arity 的两种类型的适用构造函数中哪一个是更好的构造函数。为了保持向后兼容性,非泛型类型的ctor必须始终获胜。

  

构造函数不支持类型推断是否存在实际原因?

是。即使该功能的好处超过其成本 - 这是相当大的 - 但这还不足以实现功能。这个功能不仅必须是一个净赢,它必须是一个净赢,相比我们可能投资的所有其他可能的功能。它也必须比花时间更好我们可以努力解决错误,性能工作以及其他可能的方面。理想情况下,它必须适合发布的“主题”。

此外,正如您正确指出的那样,通过使用工厂模式,您可以获得此功能的好处,而无需实际拥有该功能。简单的解决方法的存在使得功能实现的可能性降低。

此功能长期以来一直列在可能的功能列表中。它实际上从未在列表中足够高的地方实现。

2015年3月更新

建议的功能使其足够接近C#6列表顶部的指定和设计,但随后被剪切。

答案 1 :(得分:18)

public class MyType<T> 
{ 
   private readonly T field; 
   public MyType(T value) { field = value; } 
} 

他们可以,没有必要再次告诉构造函数“T是什么”,因为你已经在类的变换中已经这样做了。

你的工厂也不正确,你需要public class MyTypeFactory<T>而不只是public class MyTypeFactory - 除非你在MyType类中宣布工厂

编辑更新:

嗯,42是长,短,是int还是其他什么?

假设您有以下内容

class Base
{
   public virtual void DoStuff() { Console.WriteLine("Base"); }
}

class Foo : Base
{
   public override void DoStuff() { Console.WriteLine("Foo");  }
}

然后你做了这个

var c = new Foo();

var myType = new MyType(c);

您希望使用foo还是base?我们需要告诉编译器使用什么代替T

当你真的想进入base

类型时

因此

var myType = new MyType<Base>(c);

答案 2 :(得分:12)

泛型类型推断不能像你希望的那样对构造函数起作用的主要原因是因为当你声明的所有类都是“MyType&lt; T&gt;”时,类“MyType”甚至不存在。请记住,同时拥有两者是合法的:

public class MyType<T> {
}

public class MyType {
}

两者都是合法的。如果您确实声明了两者,并且它们都声明了冲突的构造函数,您将如何消除语法歧义。

答案 3 :(得分:1)

构造函数需要与类本身具有相同的通用规范。否则,将无法知道示例中的int是否与类或构造函数相关。

var obj = new MyType<int>(42);

这是带有构造函数MyType<T>的类MyType(int)还是带有构造函数MyType的类MyType<T>(T)

答案 4 :(得分:0)

虽然之前已经多次回答,但我觉得我需要澄清一件事:C#支持构造函数的泛型类型推断。问题是,它既不支持向构造函数添加泛型参数,也不支持 type 泛型类型推断。想要推断类型本身的泛型类型参数与要求Foo.Bar(0)推断为Foo<int>.Bar(0)基本相同。