由于泛型基类,不能使用多态

时间:2010-10-16 13:54:40

标签: c# generics polymorphism

我创建了基本泛型类,没有只有一个方法的字段

public class Base<T> where T:class
{
  public static T Create()
  {
     // create T somehow
  }
}

public class Derived1 : Base<Derived1>
{
}

public class Derived2 : Base<Derived2>
{
}


public class Program
{
    bool SomeFunction()
    {
     // Here I need reference to base class
     Base baseref; // error here 

     switch(somecondition)
     {
       case 1:
        baseref = Derived1.Create();
       break;

       case 2:
        baseref = Derived1.Create();
       break

     }

     // pass baseref somewhere     
    }
}

一个明显的选择是将基类转换为接口,但这是不可能的,因为接口不能包含静态方法。

我想我需要一些中间基类。请建议

4 个答案:

答案 0 :(得分:6)

您必须从Base类中删除通用参数,您可以将其移至Create方法:

public class Base 
{
    public static T Create<T>() where T : class
    {
        return Activator.CreateInstance<T>();
    }
}

public class Derived1 : Base
{
}

public class Derived2 : Base
{
}

答案 1 :(得分:3)

初步评估

有了这句话,

public class Derived1 : Base<Derived1> {

根据基类,您以两种不同的方式使用Derived1。

你有效地告诉C#编译器Derived1:

  1. 继承Base
  2. 和Base通过非继承方式使用Derived1的实例。
  3. 这没有错(如果这是你真正想要的),但对于大多数编程场景来说这是不寻常的;你通常选择其中一个。但是,您的逻辑的好处是:您不仅通过继承具有Derived1的隐式实例(对于任何其他派生类也是如此),但基类可以处理该相同派生的其他外部实例通过类型参数<T>

    输入

    我在Base类中看到的一个问题是,当按预期使用工厂方法时,它会变成一种循环方案,因为,为了支持所有派生类,它需要支持class Base<T> where T:Base<T>之类的东西。这几乎是不可能宣布的,因为你必须以循环的方式说:Base<Base<Base<!!!>>> baseref = null;其中!!!代表无穷多个相同的数字。


    一种解决方案......

    一种可能的(强大的解决方案)是将Type参数从类移动到工厂Create方法,并将其用法限制为Base类类型,如下所示:

    using System;
    
    public abstract class Base 
    {
        public static T Create<T>() where T : Base
        {
            return Activator.CreateInstance<T>();
        }
    
    }
    

    注意:我已经创建了基类抽象,它将实例化限制为派生类型;但是你仍然可以使用基类引用(参见下面的switch语句用法)。

    这些派生类仍然继承自base。

    public class Derived1 : Base
    {
    }
    
    public class Derived2 : Base
    {
    }
    

    您的工厂方法仅限于创建派生类型的实例。逻辑已被交换,因此派生类型被赋予工厂方法而不是在其上调用工厂方法。

    public class Program
    {
        bool SomeFunction()
        {
    
        Base baseref = null;
    
         switch(DateTime.Now.Second)
         {
           case 1:
            baseref = Base.Create<Derived1>();  // OK
           break;
    
           case 2:
            baseref = Base.Create<Derived2>();  //OK
            break;
    
           case 60:
            baseref = Base.Create<string>(); //COMPILE ERR - good because string is not a derived class
            break;
         }
    
         // pass baseref somewhere     
        }
    }
    

答案 2 :(得分:2)

public abstract class Base
{
}

public class Base<T> : Base where T : class
{
    public static T Create()
    {
        // create T somehow
    }
}

public class Derived1 : Base<Derived1>    // also inherits non-generic Base type
{
}

public class Derived2 : Base<Derived2>    // also inherits non-generic Base type
{
}

答案 3 :(得分:1)

如何创建接口并让抽象类实现接口?