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

Jac*_*ock 7 c# generics static-methods

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

class BClass<T>
{
  public static BClass<T> Create()
  {
    return new BClass<T>();
  }
 }
Run Code Online (Sandbox Code Playgroud)

从这里我导出一个类并为基类指定一个模板参数

class DClass : BClass<int> { }
Run Code Online (Sandbox Code Playgroud)

当我尝试使用静态方法创建D的实例时出现问题

class Program
{
  static void Main(string[] args)
  {
    DClass d = DClass.Create();
  }
}
Run Code Online (Sandbox Code Playgroud)

给出编译器错误"无法将类型'Test.BClass <int>'隐式转换为'Test.DClass'."

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

DClass d = (DClass)DClass.Create();
Run Code Online (Sandbox Code Playgroud)

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

BClass<int> d = DClass.Create();
Run Code Online (Sandbox Code Playgroud)

Dan*_*Tao 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
Run Code Online (Sandbox Code Playgroud)

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

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

// code elsewhere
var shape = DClass.Create<DClass>();
Run Code Online (Sandbox Code Playgroud)

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


Luc*_*ero 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();
    }
}
Run Code Online (Sandbox Code Playgroud)