使用C#泛型扩展?

时间:2010-11-09 17:27:49

标签: c# generics inheritance polymorphism

我想创建一个可扩展的嵌套结构,看起来我应该能够使用泛型来做到这一点,尽管我可能没有“正确地”使用它们。

我希望能够从GroupType和/或OptionType创建子类。问题是我无法对泛型类型执行new操作,即使我指定它们只能是某种基类型。

有什么办法可以做我想做的事吗?

public class AllInfo<GroupType, OptionType> 
    where GroupType: GroupBase<OptionType>
    where OptionType: OptionBase
{
    public List<string> Names { set; get; }
    public List<GroupType> Groups { set; get; }

    public AllInfo()
    {
        DataSet ds = DatabaseRetreival();
        this.Groups.add(new GroupType(ds["Name"], ds["Type"]));
    }

}

public class GroupBase<OptionType> 
    where OptionType: OptionBase
{
    public string Name { set; get; }
    public string Type { set; get; }
    public List<OptionType> Options { set; get; }

    public GroupBase(string name, string type)
    {
         this.Name = name;
         this.Type = type;

         DataSet ds = DatabaseRetreival(this.Type);
         this.Options.Add(new OptionType(ds["Name"]));
    }
}

public class OptionBase
{
    public string Name { set; get; }

    public OptionBase(string name)
    {
        this.Name = name;
    }
}

4 个答案:

答案 0 :(得分:4)

您必须指定类必须具有默认构造函数。

where GroupType: GroupBase<OptionType>, new()

查看this article并跳转到标题为通用约束的部分。

答案 1 :(得分:2)

您无法指定泛型类应具有的构造函数。构造函数不是继承的,因此即使您指定的基类具有该构造函数,从该类派生的类也不必具有该构造函数。

您可以要求的唯一构造函数是无参数构造函数:

where GroupType: GroupBase<OptionType>, new()

因为只允许使用无参数构造函数,您还可以使用虚方法将数据放入对象中,例如:

GroupType group = new GroupType();
group.Init(ds["Name"], ds["Type"]);
this.Groups.add(group);

答案 2 :(得分:1)

编译器不能允许这样做,因为它不能保证OptionType具有带正确签名的构造函数。但是您可以传递工厂函数而不是直接调用构造函数:

public class Foo<T> 
{
    private List<T> myObjects;

    public Foo(Func<string, T> factory))
    {
        myObjects = new List<T>();
        foreach (string s in GetDataStrings())
            myObjects.Add(factory(s));
    }
}

因此,如果你有一个带有构造函数的Bar类,那么你可以这样做:

Func<string,Bar> barFactory = x => new Bar(x);
var foo = new Foo<Bar>(barFactory);

答案 3 :(得分:0)

你遇到的问题基本上是基于你试图通过继承/泛型缓解的大量类耦合。我建议你重新检查为什么你觉得这是必要的。此任务最终将引导您进入接口,基于服务的编程以及像Ninject或Castle Windsor这样的IoC。

但是,如果您想要快速修复,进一步增加代码复杂性(因为除了更改编码原则之外,您没有此处的非复杂选项),使用抽象/虚拟方法,也许称之为Bind(),而不是构造函数。

[为tl;博士加粗]