C# 如何向C中非泛型类的构造函数添加泛型约束#

C# 如何向C中非泛型类的构造函数添加泛型约束#,c#,.net,oop,generics,C#,.net,Oop,Generics,如标题所示,我希望执行以下操作,但编译器不允许: public class MyClass { private List<SomeSupertype> myList; public MyClass<T> (ICollection<T> elements) where T : SomeSupertype { myList = new List<SomeSuperType> (); foreac

如标题所示,我希望执行以下操作,但编译器不允许:

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(ICollection元素),其中T:SomeSupertype
{
myList=新列表();
foreach(元素中的SomeSupertype元素){
添加(元素);
}
}
}
不知何故,似乎不可能向本身不是泛型的类的构造函数添加泛型参数。请注意,MyClass应该是非泛型类型,因为客户机在构造MyClass后不必区分不同类型的MyClass

有人能帮我弄清楚吗?这可能吗?它当然是用Java编写的:)


编辑:我忘了提到我正在使用.NET 3.5,因此不支持协变泛型。

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

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()
    {
    }
}
公共类MyClass
{
私有列表myList=新列表();
公共静态MyClass MyClassBuilder(ICollection元素),其中T:SomeSuperType
{
var myClass=新的myClass();
foreach(元素中的SomeSuperType元素)
{
myClass.myList.Add(元素);
}
返回myClass;
}
受保护的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);
        }
    }
}
//将所有方法放在这里
公共类MyClass
{
受保护列表myList=新列表();
受保护的MyClass()
{
}
}
//此类将仅定义泛型构造函数
公共类MyClass:MyClass,其中T:SomeSuperType
{
公共MyClass(ICollection元素)
{
foreach(元素中的SomeSuperType元素)
{
添加(元素);
}
}
}
(这忽略了一个事实,即,正如Anton所写,在C#>=4.0中,您可以简单地接受一个
IEnumerable
,并感到高兴)

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);
    }
}
公共类MyClass
{
私人名单;
私有MyClass(列表myList)
{
this.myList=myList;
}
公共静态MyClass创建(ICollection元素)
其中T:SomeSupertype
{
var myList=新列表(元素);
foreach(元素中的SomeSupertype元素)
{
添加(元素);
}
返回新的MyClass(myList);
}
}
即使在.NET 3.5中,您也可以使用LINQ简化列表创建,顺便说一下:

var myList = elements.Cast<SomeSuperType>().ToList();
var myList=elements.Cast().ToList();
在C#中无法执行此操作。这是一件好事,因为我们不需要与类不匹配的构造函数。但是仍然有几种方法可以实现你的目标

最简单的方法(如果使用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);
        }
    }
}
公共类MyClass
{
私人名单;
公共MyClass(IEnumerable元素)
{
myList=新列表();
foreach(元素中的SomeSupertype元素){
添加(元素);
}
}
}
现在您可以调用构造函数,而不用考虑将派生类型集合强制转换为基类型集合

List<SomeDerivedClass> col = new List<SomeDerivedType>();
MyClass obj1 = new MyClass(col)
List col=new List();
MyClass obj1=新的MyClass(col)
第二种解决方案是,您可以通过使用LINQ强制转换集合来调用构造函数

MyClass obj1 = new MyClass(col.Cast<SomeSuperClass>());
MyClass obj1=新的MyClass(col.Cast());
第三种解决方案是,您可以创建静态泛型方法来构造类的新对象

public static MyClass Construct<T>(ICollection<T> elements) where T : ClassA
{
    return new MyClass(elements.Cast<ClassA>().ToArray());
}
公共静态MyClass构造(ICollection元素),其中T:ClassA
{
返回新的MyClass(elements.Cast().ToArray());
}

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

如果您使用的是.NET 4,为什么不让一个非泛型构造函数采用
IEnumerable
IEnumerable
1`是协变的,所以无论何时只要
T:SomeSupertype
@Anton:经过一些重新编码和解释,似乎答案是值得的,协变就会解决问题。我可能应该提到我正在使用.NET3.5