【问题标题】:Overriding a method returning a generic class覆盖返回泛型类的方法
【发布时间】:2011-11-30 15:08:01
【问题描述】:

在我的 Silverlight 4 应用程序中,我开始创建和使用一些泛型,现在我偶然发现了以下问题:

在一个非泛型类中,我有一个抽象方法,它返回一个泛型类:

public abstract class DTO_Base()
{
  public abstract ServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}

泛型类的定义方式如下:

public abstract class ServiceModelBase<RootNodeType> where RootNodeType : ServiceNodeBase

自然,从 DTO_Base 派生的类将不得不重写 CreateBusinessObject 方法:

public class DTO_Editor : DTO_Base
{
  public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
  {
    // the object to return have to be of type ServiceModelEditor
    // which is derived from ServiceModelBase<ServiceNodeEditor>
    // public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>

    // ServiceNodeEditor is derived from ServiceNodeBase
    // public class ServiceNodeEditor : ServiceNodeBase
    ServiceModelEditor target = new ServiceModelEditor()

    ...
    Functions to populate the 'target'
    ...

    return target;
  }
}

return target; 行会导致错误,指出无法在ServiceModelBase&lt;ServiceNodeBase&gt; 中隐式转换类型ServiceModelEditor。此外,通过目标作为ServiceModelBase&lt;ServiceNodeBase&gt; 的显式转换不起作用。

我必须如何实现这个方法才能工作?

【问题讨论】:

    标签: c# generics inheritance overriding


    【解决方案1】:

    试试这个:

    public interface IDTO<Node> where Node : ServiceNodeBase
    {
        ServiceModelBase<Node> CreateBusinessObject();
    }
    public abstract class DTO_Base<Model,Node> : IDTO<Node>
        where Model : ServiceModelBase<Node>
        where Node : ServiceNodeBase
    {
        public abstract Model CreateBusinessObject();
    
    
        #region IDTO<Node> Members
    
        ServiceModelBase<Node> IDTO<Node>.CreateBusinessObject()
        {
            return CreateBusinessObject();
        }
    
        #endregion
    }
    
    public class DTO_Editor : DTO_Base<ServiceModelEditor, ServiceNodeEditor>
    {
    
        public override ServiceModelEditor CreateBusinessObject()
        {
            // the object to return have to be of type ServiceModelEditor
            // which is derived from ServiceModelBase<ServiceNodeEditor>
            // public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>
    
            // ServiceNodeEditor is derived from ServiceNodeBase
            // public class ServiceNodeEditor : ServiceNodeBase
            ServiceModelEditor target = new ServiceModelEditor();
    
    
            return target;
    
        }
    }
    

    我以前也遇到过类似的问题,唯一合理的做法是使核心基类也通用。您可以删除Model 泛型参数(和接口),它看起来会不那么可怕,但您会失去对方法之外ServiceModelEditor 功能的可见性。

    【讨论】:

    • 非常感谢,这行得通!即使没有接口,那么你创建的接口是否有必要让我免于以后的麻烦?
    【解决方案2】:

    事实上,您得到返回ServiceModelBase&lt;ServiceNodeBase&gt;。一种选择是使您的基类通用:

    public abstract class DtoBase<T> where T : RootNodeType
    {
        public abstract ServiceModelBase<T> CreateBusinessObject();
    }
    

    然后:

    public class DtoEditor : DtoBase<ServiceNodeBase>
    {
        public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
        {
            ...
        }
    }
    

    【讨论】:

    • "公共类 DtoEditor : DtoBase" 我认为
    • @KooKiz:我不这么认为——就方法的返回值而言。 ServiceModelEditor 必须派生自 ServiceModelBase&lt;ServiceNodeBase&gt;
    • 是的,但在代码 cmets 中已经提到 ServiceModelEditor 派生自 ServiceModelBase
    • @KooKiz:那问题内部不一致,基本上:)
    • 那么如何始终如一地构建呢?从 ServiceModelBase 派生 ServiceModelEditor 的重点是从 ServiceModelBase 类到 ServiceNodeEditor 的泛型类型。如果我将它设置为 ServiceNodeBase,我根本不需要整个泛型方法。这个泛型的东西似乎让整个构造变得更加复杂和混乱,或者我可能只是以错误的方式使用泛型。
    【解决方案3】:

    如果您使用的是 .Net 4.0,我建议您使用接口来定义您的 ServiceModelBase 并在该接口泛型类型上指定 out 方差修饰符:

    class ServiceNodeBase { }
    class ServiceNodeEditor : ServiceNodeBase {/*implementation*/}
    //
    interface IServiceModelBase<out RootNodeType>
        where RootNodeType : ServiceNodeBase { 
    }
    class ServiceModelEditor : IServiceModelBase<ServiceNodeEditor> {
        /*implementation*/
    }
    //
    abstract class DTO_Base {
        public abstract IServiceModelBase<ServiceNodeBase> CreateBusinessObject();
    }
    class DTO_Editor : DTO_Base {
        public override IServiceModelBase<ServiceNodeBase> CreateBusinessObject() {
            return new ServiceModelEditor();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      • 2020-07-16
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2014-04-18
      相关资源
      最近更新 更多