我似乎无法理解 C# 中的泛型。
基本上我有一个名为 ConfigWorker
的基类和一堆子类,它们都应该使用它们自己的派生自 BaseConfig
的配置类.
我想使用的 ConfigWorker 类应该在运行时动态确定,给定类的名称作为参数。
我可以根据它的名称实例化子类,但无论我尝试什么,我都无法转换为合理的基类。
这是我的代码:
namespace DocumentHandler
{
public class BaseConfig
{
}
public class ConfigWorker<T> where T : BaseConfig
{
public virtual void Work(T options)
{
}
}
public class Worker1 : ConfigWorker<Worker1.Config>
{
public class Config : BaseConfig
{
public string test = "";
}
public override void Work(Config options)
{
//do something
}
}
public class Worker2 : ConfigWorker<Worker2.Config>
{
public class Config : BaseConfig
{
public string test = "";
}
public override void Work(Config options)
{
//do something else
}
}
public class Test
{
public static BaseConfig config;
public static void test()
{
(Activator
.CreateInstance(Type.GetType("DocumentHandler.Worker2"))
as ConfigWorker<BaseConfig>)
.Work(config);
}
}
}
关键是
(Activator
.CreateInstance(Type.GetType("DocumentHandler.Worker2"))
as ConfigWorker<BaseConfig>)
.Work(config);
类型转换到ConfigWorker<BaseConfig>
返回 null,因为无法执行转换。
尝试简单地转换为 ConfigWorker
不编译,因为缺少类型参数。
还有什么我可以尝试的吗? CreateInstance
显然只是返回一个对象,我需要转换它才能调用 Work
方法
感谢任何帮助。
最佳答案
Worker2 的实例不是 ConfigWorker<BaseConfig>
!这是一个ConfigWorker<Worker2.Config>
.这是两种完全不同的类型。通用类是不变的。只有接口(interface)和委托(delegate)可以协变或逆变。
在您的示例中,ConfigWorker
在 T
中甚至是反变 ,意味着您使用 T
作为方法的输入参数的类型。所以你的尝试实际上是危险的。
想象一下你的行会起作用:你得到一个类型为 ConfigWorker<BaseConfig>
的变量, 所以你可以依赖这个实例有一个方法 Work()
这需要 BaseConfig
(或从中派生出的东西)作为参数。所以没有什么能阻止你这样调用它
worker.Work(new Worker1.Config());
编译正常。但是等一下!你的台词不是说worker
吗?是 Worker2
? Worker2
实例只能处理 Worker2.Config
争论!
您以这种方式完全失去了类型安全性(好吧,如果允许的话,您会这样做)。
您的类(class)设计存在缺陷。
关于c# - 使用泛型转换为基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57802708/