从派生类中的静态方法创建泛型类实例

时间:2010-05-27 11:45:51

标签: c# generics static-methods

我在C#中有一个类,其模板和静态方法类似于

class BClass<T>
{
  public static BClass<T> Create()
  {
    return new BClass<T>();
  }
 }

由此我派生出一个类并为基类

指定一个模板参数
class DClass : BClass<int> { }

当我尝试使用静态方法创建D

的实例时出现问题
class Program
{
  static void Main(string[] args)
  {
    DClass d = DClass.Create();
  }
}

给出编译器错误“无法将类型'Test.BClass&lt; int&gt;'隐式转换为'Test.DClass'。”

添加以下强制转换会导致运行时强制转换异常。

DClass d = (DClass)DClass.Create();

是否有任何succint方法允许静态方法创建派生类的实例?理想情况下,我想要相当于c ++ typedef,我不想要下面的语法(这确实有用)。

BClass<int> d = DClass.Create();

3 个答案:

答案 0 :(得分:7)

您希望DClass成为BClass<int>的别名。但这不是你在这里所拥有的。您所拥有的是DClass 来自 BClass<int>。因此,调用DClass.Create();会创建一个BClass<int>一个DClass(反之亦然)。

这可能会更清楚。假设你有这个层次结构:

class Rectangle {
    static Rectangle Create() {
        return new Rectangle();
    }
}

class Square : Rectangle { }

// code elsewhere
var shape = Square.Create(); // you might want this to return a square,
                             // but it's just going to return a rectangle

获得所需功能的一个选项可能是定义Create方法,如下所示:

static TClass Create<TClass>() where TClass : BClass<T>, new() {
    return new TClass();
}

// code elsewhere
var shape = DClass.Create<DClass>();

虽然这有点混乱(并且还要求你为DClass编写无参数构造函数)。如果你已经开始使用Create方法来实例化对象,可以考虑为它编写一个工厂类。

答案 1 :(得分:6)

是可能的,通过对类型本身进行类型引用。请注意,在.NET世界中,我们讨论的是泛型,而不是模板,它们的工作方式确实存在重大差异。

class BClass<T, TSelf> where TSelf: BClass<T, TSelf>, new() {
    public static TSelf Create() {
        return new TSelf();
    }
}

class DClass: BClass<int, DClass> {}

class Program {
    static void Main(string[] args) {
        DClass d = DClass.Create();
    }
}

答案 2 :(得分:1)

class BClass<T>
    {
        public static T1 Create<T1, T2>() where T1 : BClass<T2>, new()
        {
            return new T1();
        }
    }

    class DClass : BClass<int> { }

    class Program
    {
        static void Main(string[] args)
        {
            DClass d = DClass.Create<DClass, int>();
        }
    }