如何在c#中为非泛型类的构造函数添加泛型约束

本文关键字:构造函数 添加 泛型 约束 泛型类 | 更新日期: 2023-09-27 18:12:48

如标题所示,我想做以下操作,但编译器不允许:

public class MyClass
{
    private List<SomeSupertype> myList;
    public MyClass<T> (ICollection<T> elements) where T : SomeSupertype
    {
        myList = new List<SomeSuperType> ();
        foreach (SomeSupertype element in elements) {
            myList.Add (element);
        }
    }
}

在某种程度上,似乎不可能向本身不是泛型的类的构造函数添加泛型形参。请注意,MyClass应该是一个非泛型类型,因为客户端在构造MyClass后不需要区分它的不同类型。

有谁能帮我解决这个问题吗?这可能吗?在Java中肯定是这样的:)

编辑:我忘了说我使用的是。net 3.5,因此不支持协变泛型。

如何在c#中为非泛型类的构造函数添加泛型约束

c#中的构造函数不能是泛型的(事件、属性、析构函数、操作符也是如此)。考虑创建一个静态泛型工厂方法:

public class MyClass
{
    private List<SomeSupertype> myList;
    private MyClass(List<SomeSupertype> myList)
    {
        this.myList = myList;
    }
    public static MyClass Create<T>(ICollection<T> elements)
        where T : SomeSupertype
    {
        var myList = new List<SomeSuperType>(elements);
        foreach (SomeSupertype element in elements)
        {
            myList.Add(element);
        }
        return new MyClass(myList);
    }
}
即使在。net 3.5中,你也可以使用LINQ来简化列表的创建,顺便说一下:
var myList = elements.Cast<SomeSuperType>().ToList();

您可以使用工厂模式来解决您的问题:

public class MyClass
{
    private List<SomeSuperType> myList = new List<SomeSuperType>();
    public static MyClass MyClassBuilder<T>(ICollection<T> elements) where T : SomeSuperType
    {
        var myClass = new MyClass();
        foreach (SomeSuperType element in elements)
        {
            myClass.myList.Add(element);
        }
        return myClass;
    }
    protected MyClass()
    {
    }
}

或者可以创建两个类,像这样:

// Put all the methods here
public class MyClass
{
    protected List<SomeSuperType> myList = new List<SomeSuperType>();
    protected MyClass()
    {
    }
}
// This class will define only the generic constructor
public class MyClass<T> : MyClass where T : SomeSuperType
{
    public MyClass(ICollection<T> elements)
    {
        foreach (SomeSuperType element in elements)
        {
            myList.Add(element);
        }
    }
}

(这忽略了这样一个事实,即由Anton编写,在c#>= 4.0中,您可以简单地接受IEnumerable<SomeSuperType>并感到高兴)

你不能在c#中这样做。这是一件好事,因为我们不希望构造函数与class不匹配。但是仍然有几种方法可以实现你的目标。

最简单的方法(如果你使用c# 4)是使用IEnumerable代替ICollection,因为IEnumerable支持逆变。

public class MyClass
{
    private List<SomeSupertype> myList;
    public MyClass (IEnumerable<SomeSuperType> elements)
    {
        myList = new List<SomeSuperType> ();
        foreach (SomeSupertype element in elements) {
            myList.Add (element);
        }
    }
}

现在可以调用构造函数,而不必考虑将派生类型集合强制转换为基类型集合。

List<SomeDerivedClass> col = new List<SomeDerivedType>();
MyClass obj1 = new MyClass(col)

第二个解决方案,您可以通过使用LINQ强制转换集合来调用构造函数。

MyClass obj1 = new MyClass(col.Cast<SomeSuperClass>());

第三种解决方案,您可以创建静态泛型方法来构造类的新对象。

public static MyClass Construct<T>(ICollection<T> elements) where T : ClassA
{
    return new MyClass(elements.Cast<ClassA>().ToArray());
}

第四个解决方案,您可以创建一个派生自基类的泛型类,正如有人已经指出的。