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

为什么构造函数不像泛型方法那样支持类型推理?

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);

构造函数不支持类型推理是否有实际或哲学上的原因?

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

它们可以,因此没有必要再次告诉构造函数“ T 是什么”,因为您已经在类声明中这样做了。

而且您的工厂也是不正确的,您需要的不仅仅是 public class MyTypeFactory而是 public class MyTypeFactory<T>-除非您在 MyType类中声明了工厂

编辑更新:

42是长的,短的,整型的,还是别的什么?

假设你有以下信息

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);

构造函数需要与类本身具有相同的泛型规范。否则,就不可能知道示例中的 int是与类相关还是与构造函数相关。

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

是带构造函数 MyType(int)MyType<T>类,还是带构造函数 MyType<T>(T)MyType类?

构造函数不支持类型推理有什么哲学上的原因吗?

不,等你有的时候

new Foo(bar)

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

构造函数不支持类型推理是否有实际的原因?

是的。即使这个特性的好处大于它的成本(这是相当可观的) ,也不足以实现一个特性。该功能不仅必须是一个净胜利,它必须是一个 很大净胜利相比,所有其他可能的功能,我们可以投资。它也必须比把时间和精力花在错误修复、性能工作和其他我们可以投入精力的领域要好。理想情况下,它必须很好地适应发行版的任何“主题”。

此外,正如您正确地指出的,您可以通过使用工厂模式,在不实际拥有特性本身的情况下获得此特性的好处。简单变通方法的存在使得实现某个特性的可能性降低。

这个特性已经在可能的特性列表中很长时间了。它在名单上的位置从来没有高到足以实现的程度。

更新日期: 2015年3月

提出的特性使它足够接近列表的顶部,以便指定和设计 C # 6,但随后被删除。

泛型类型推断不能像您希望的那样在构造函数上工作的主要原因是,当您声明的所有内容都是“ MyType < T >”时,类“ MyType”甚至不存在。记住,同时拥有两者是合法的:

public class MyType<T> {
}

还有

public class MyType {
}

两者都是合法的。如果实际上两者都声明了,并且两者都声明了一个冲突的构造函数,那么如何消除语法的歧义呢。

虽然这个问题以前已经被回答过很多次,但是我觉得我需要澄清一件事: 构造函数上的 C # 支撑物泛型类型推断。问题是,它既不支持向构造函数添加泛型参数,也不支持 类型泛型类型推断。想要推断 自己打出来的泛型类型参数基本上与要求 Foo.Bar(0)推断 Foo<int>.Bar(0)是一样的。