简体   繁体   English

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

[英]Why can't the C# constructor infer type?

Why is type inference not supported for constructors the way it is for generic methods?为什么构造函数不支持泛型方法的类型推断?

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>?

Though you could get around this with a factory class,虽然你可以通过工厂课程来解决这个问题,

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

Is there a practical or philosophical reason why the constructor can't support type inference?构造函数不能支持类型推断是否有实际或哲学上的原因?

Is there a philosophical reason why the constructor can't support type inference?构造函数不能支持类型推断有哲学上的原因吗?

No. When you have不,当你有

new Foo(bar)

then we could identify all types called Foo in scope regardless of generic arity, and then do overload resolution on each using a modified method type inference algorithm.然后我们可以在范围内识别所有称为 Foo 的类型,而不管泛型数量如何,然后使用修改的方法类型推断算法对每个类型进行重载解析。 We'd then have to create a 'betterness' algorithm that determines which of two applicable constructors in two types that have the same name but different generic arity is the better constructor.然后,我们必须创建一个“更好”算法,以确定具有相同名称但具有不同泛型的两种类型中的两个适用构造函数中的哪一个是更好的构造函数。 In order to maintain backwards compatibility a ctor on a non-generic type must always win.为了保持向后兼容性,非泛型类型的 ctor 必须始终获胜。

Is there a practical reason why the constructor can't support type inference?构造函数不能支持类型推断有实际原因吗?

Yes.是的。 Even if the benefit of the feature outweighs its costs -- which are considerable -- that's not sufficient to have a feature implemented.即使该功能的好处超过其成本——这是相当大的——也不足以实现一个功能。 Not only does the feature have to be a net win, it has to be a large net win compared to all the other possible features we could be investing in. It also has to be better than spending that time and effort on bug fixing, performance work, and other possible areas that we could put that effort.与我们可以投资的所有其他可能的功能相比,该功能不仅必须是净赢,而且必须是巨大的净赢。它还必须比花费时间和精力在错误修复、性能上更好工作,以及我们可以投入的其他可能领域。 And ideally it has to fit in well to whatever the "theme" is of the release.理想情况下,它必须很好地适应发行版的“主题”。

Furthermore, as you correctly note, you can get the benefits of this feature without actually having the feature itself, by using a factory pattern.此外,正如您正确指出的那样,您可以通过使用工厂模式获得此功能的好处,而无需实际拥有该功能本身。 The existence of easy workarounds makes it less likely that a feature will ever be implemented.简单的变通方法的存在降低了实现某个功能的可能性。

This feature has been on the list of possible features for a long time now.很长一段时间以来,此功能一直在可能的功能列表中。 It's never been anywhere near high enough on the list to actually get implemented.它在列表中的位置从来没有足够高以至于无法实际实施。

UPDATE March 2015 2015 年 3 月更新

The proposed feature made it close enough to the top of the list for C# 6 to be specified and designed, but was then cut.提议的功能使它足够接近 C# 6 的列表顶部,以便指定和设计,但随后被删除。

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

they can, there is no need to tell the constructor 'what T is' again, seeing as you have already done that in the class decleration.他们可以,没有必要再次告诉构造函数“T 是什么”,因为您已经在类声明中这样做了。

also your factory is incorrect, you need to have public class MyTypeFactory<T> not just public class MyTypeFactory - unless you declare the factory inside the MyType class您的工厂也不正确,您需要拥有public class MyTypeFactory<T>而不仅仅是public class MyTypeFactory - 除非您在MyType类中声明工厂

Edit for update:编辑更新:

Well, is 42 a long, a short, an int, or something else?那么,42 是 long、short、int 还是别的什么?

Let's say you have the following假设您有以下内容

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

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

Then you did this然后你做了这个

var c = new Foo();

var myType = new MyType(c);

Would you expect foo to be used, or base ?您希望使用foo还是base We need to tell the compiler what to use in place of T我们需要告诉编译器用什么代替T

When you really wanted to on type base当你真的想在类型base

Hence the因此

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

The main reason generic type inference can't work on constructors like you wish is because the class "MyType" doesn't even exist when all you've declared is "MyType<T>".泛型类型推断不能像您希望的那样在构造函数上起作用的主要原因是,当您声明的所有内容都是“MyType<T>”时,“MyType”类甚至都不存在。 Remember it is legal to have both:请记住,两者兼有是合法的:

public class MyType<T> {
}

and

public class MyType {
}

Both would be legal.两者都是合法的。 How would you disambiguate your syntax if you did in fact declare both, and both of them declared a conflicting constructor.如果您确实声明了两者,并且它们都声明了一个冲突的构造函数,那么您将如何消除语法歧义。

The constructor needs to have the same generic specification as the class itself.构造函数需要与类本身具有相同的通用规范。 Otherwise it would be impossible to know if the int in your example would relate to the class or to the constructor.否则,将无法知道示例中的int是否与类或构造函数相关。

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

Would that be class MyType<T> with constructor MyType(int) or class MyType with constructor MyType<T>(T) ?那是带有构造函数 MyType<T MyType<T>的类MyType MyType(int)还是带有构造函数MyType<T>(T)的类 MyType ?

Although this has been answered many times before, I feel I need to clarify one thing: C# supports generic type inference on constructors.虽然这个问题之前已经回答过很多次了,但我觉得我需要澄清一件事:C#支持构造函数的泛型类型推断。 The problem is, it doesn't support neither adding generic parameters to constructors nor type generic type inference.问题是,它既不支持向构造函数添加泛型参数也不支持类型泛型类型推断。 Wanting to infer generic type argument of the type itself is basically the same as requiring Foo.Bar(0) to infer to Foo<int>.Bar(0) .想要推断类型本身的泛型类型参数与要求Foo.Bar(0)推断Foo<int>.Bar(0)基本相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM