如何将Class <derived>转换为Class <base />?

时间:2015-11-19 16:10:26

标签: c# .net generics

我有一个带有多个派生类的基类:

class Base { }

class Derived1 : Base { }

class Derived2 : Base { }

然后我有一个将此类作为泛型类型的worker类:​​

class WorkerClass<T> where T : Base, new()
{
    WorkerClass() { }

    void DoStuff()
    {
        T container = new T();
        // do stuff
    }
}

问题是当我实例化WorkerClass时,我只将类型作为变量。我想这样做:

void DoStuff(Type type)
{
    WorkerClass<Base> worker_class = null;

    if(type == typeof(Derived1))
    {
        worker_class = new WorkerClass<Derived1>();  // compiler error
    }
    else if(type == typeof(Derived2))
    {
        worker_class = new WorkerClass<Derived2>();  // compiler error
    }

    // lots of common code with worker_class
    worker_class.DoStuff();
}

但编译器抱怨隐含地将WorkerClass<Derived>强制转换为WorkerClass<Base>。显式转换也会产生错误。编译器建议定义public static implicit operator WorkerClass<T>(WorkerClass<Derived>),但我不确定该代码是什么样的。我显然可以将所有逻辑放在if-else中,但这似乎是不必要的重复。

3 个答案:

答案 0 :(得分:2)

我可能会误读你的意图,但我认为你可以使用具有约束的泛型来做这样的事情:

dispatch_async(dispatch_get_main_queue(), {
    self.tableView.reloadData()
})

从那里你只需要打电话,例如:

void DoStuff<T>() where T : Base, new()
{
  WorkerClass<T> worker_class = new WorkerClass<T>();

  // lots of common code with worker_class
  worker_class.DoStuff();
}

答案 1 :(得分:1)

我对您的代码进行了多次更正以使其正常工作。您的WorkerClass<T>也需要从Base类继承,如果要执行的代码而不是{{1},则可能需要覆盖超类中的DoStuff调用} DoStuff类中的方法。

Base

答案 2 :(得分:0)

您可以使用covariance,但仅在接口和委托上支持它。尝试介绍接口IWorkerClass<out T>out关键字将模板类型T标记为协变。

interface IWorkerClass<out T> 
{
    void DoStuff();
}

class WorkerClass<T> : IWorkerClass<T> where T : Base, new() 
{ 
    public void DoStuff() { }
}

然后在代码示例中使用接口而不是类:

void DoStuff(Type type)
{
    IWorkerClass<Base> worker_class = null;

    if(type == typeof(Derived1))
    {
        worker_class = new WorkerClass<Derived1>();  // NO compiler error
    }
    else if(type == typeof(Derived2))
    {
        worker_class = new WorkerClass<Derived2>();  // NO compiler error
    }

    // lots of common code with worker_class
    worker_class.DoStuff();
}