为什么C#不接受带有泛型参数的构造函数要求?

Why C# don't accept constructor requirements with parameters on generics?

使用C泛型,您可以拥有这样的类:

1
class Foo<T> where T:new() {}

这意味着T类型应该有一个不带参数的构造函数。如果我们能有:

1
2
3
4
5
6
7
8
class Foo<T> where T : new(string)
{
    private T CreateItem()
    {
        string s="";
        return new T(s);
    }
}

有什么理由微软没有将此功能添加到语言中吗?


Is there any reason that Microsoft haven't added this feature to the language?

您所描述的特性是更一般特性的特定情况,"允许存在需要特定方法的约束"。例如,您可能会说:

1
2
3
4
void M<T>(T t) where T has an accessible method with signature double Foo(int)
{
    double x = t.Foo(123);
}

我们在C中没有这个特性,因为特性必须通过成本效益分析来证明。从设计和实现的角度来看,这将是一个相当昂贵的功能——这一功能不仅会将需求驱动到C语言,而且还会驱动到每一种.NET语言。什么是令人信服的优势,证明该功能的合理性?

另外:假设我们设计了这个特性。如何有效实施?通用类型系统中的约束经过精心设计,这样抖动一旦生成有效的代码,就可以为每个引用类型共享这些代码。如何为任意方法模式匹配生成有效的代码?当方法的槽可以在编译时被知道时,这种高效的分派就非常简单;有了这个特性,我们将不再具有这种优势。

您想要的特性是相同的特性,只是方法的类型被限制为构造函数。

记住,泛型的目的是让您编写泛型类型的代码。如果您需要的约束比类型系统中可以捕获的约束更具体,那么您可能试图滥用泛型。


与其试图猜测微软为什么要决定一个特定的实现,不如使用工厂模式为您提供一个解决方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface IFactory<T>
{
   T CreateItem(string s);
}

class Foo<TFactory,T> where TFactory : IFactory<T>, new()
{
    private T CreateItem()
    {
        var factory = new TFactory();
        string s="";
        return factory.CreateItem(s);
    }
}

使用此模式,假设您有一个类Bar,它有一个采用单个字符串的构造函数:

1
2
3
4
5
public class Bar
{
   public Bar(string laa)
   {}
}

你只需要一个实现IFactoryBarFactory

1
2
3
4
5
6
7
8
public class BarFactory : IFactory<Bar>
{
   public BarFactory () {}
   public Bar CreateItem(string s)
   {
      return new Bar(s);
   }
}

现在你可以用那个工厂和foo

1
var foo = new Foo<BarFactory,Bar>(); // calls to CreateItem() will construct a Bar


当我需要一个用参数调用构造函数的通用函数时,我采用的解决方案是使用反射来查找和调用它。

考虑到我同时控制了泛型和它被实现的所有类(而这个函数是构造这些类的唯一地方),我认为最好给类一个默认的构造函数,并在它们都实现的接口中添加一个初始化方法。

(允许将静态方法一般添加到接口的解决方案是理想的。)