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

本文关键字:构造函数 参数 泛型 不接受 为什么 | 更新日期: 2023-09-27 18:05:32

使用c#泛型,你可以有这样一个类:

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

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

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

微软没有在语言中添加这个特性有什么原因吗?

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

微软没有在语言中添加这个特性有什么原因吗?

你描述的特性是更一般的特性"允许需要特定方法存在的约束"的一个特殊情况。例如,你可以说:

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

我们在c#中没有这个特性,因为特性必须通过成本效益分析来证明。从设计和实现的角度来看,这将是一个相当昂贵的特性——这个特性不仅会将需求推到c#上,而且会推到所有。net语言上。这个功能有什么令人信服的好处?

而且:假设我们确实设计了那个功能。如何有效地实现?泛型类型系统中的约束经过精心设计,因此抖动可以在一次生成有效的代码,然后可以为每个引用类型共享。我们如何为任意方法模式匹配生成高效的代码?当可以在编译时知道方法的槽位时,这种有效的分派是相当直接的;有了这个功能,我们就不再有这种优势了。

您想要的功能是相同的功能,只是将方法类型限制为构造函数。

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

与其猜测Microsoft决定采用特定实现的原因,不如为您提供一种变通方法,使用工厂模式

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

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

考虑到我既控制了泛型,又控制了实现它的所有类(并且这个函数是构造这些类的唯一地方),我认为我可能会更好地给这些类一个默认构造函数,并在它们实现的接口中添加一个Initialize方法。

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