【问题标题】:Extending using C# generics?使用 C# 泛型进行扩展?
【发布时间】:2011-05-07 09:37:27
【问题描述】:

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

我希望能够从 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;
    }
}

【问题讨论】:

    标签: c# generics inheritance polymorphism


    【解决方案1】:

    你必须指定类必须有一个默认构造函数。

    where GroupType: GroupBase<OptionType>, new()
    

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

    【讨论】:

    【解决方案2】:

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

    您唯一需要的构造函数是无参数构造函数:

    where GroupType: GroupBase<OptionType>, new()
    

    既然只让你使用无参数构造函数,你也可以使用虚方法将数据放入对象中,例如:

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

    【讨论】:

      【解决方案3】:

      编译器不允许这样做,因为它不能保证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);
      

      【讨论】:

        【解决方案4】:

        您遇到的问题基本上是基于您试图通过继承/泛型来缓解的大量类耦合。我建议你重新审视一下为什么你觉得这是必要的。这一探索最终将引导您了解接口、基于服务的编程和 IoC,例如 Ninject 或 Castle Windsor。

        但是,如果您想要一个快速解决方案以进一步增加代码复杂性(因为除了改变您的编码理念之外,这里没有不复杂的选项),使用抽象/虚拟方法,或许称它为 Bind(),而不是构造函数。

        [粗体表示 tl;dr]

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多