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

时间:2011-08-15 15:50:25

标签: c# generics constructor

使用C#Generics,您可以拥有这样的类:

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

这意味着类型T应该有一个没有参数的构造函数。如果我们有这样的话会很好:

class Foo<T> where T : new(string)
{
    private T CreateItem()
    {
        string s="";
        return new T(s);
    }
}

Microsoft是否有任何理由未将此功能添加到该语言中?

3 个答案:

答案 0 :(得分:10)

  

Microsoft是否有任何理由未将此功能添加到该语言中?

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

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 :(得分:7)

不是试图猜测微软决定某个特定实现的原因,而是使用工厂模式为您解决方法

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,其构造函数采用单个字符串:

public class Bar
{
   public Bar(string laa)
   {}
}

您只需要BarFactory来实现IFactory<Bar>

public class BarFactory : IFactory<Bar>
{
   public BarFactory () {}
   public Bar CreateItem(string s)
   {
      return new Bar(s);
   }
}

现在您可以将该工厂与Foo一起使用

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

答案 2 :(得分:1)

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

鉴于我已经控制了泛型和它所实现的所有类(并且这个函数是构造这些类的唯一的地方),我想我可能更好地给类一个默认的构造函数和在他们全部实现的界面中添加了一个Initialize方法。

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