c# - 参数类型不可分配给参数类型,它应该是

标签 c# generics

我定义了一个类 CommandProcessor<T>因为有 T派生自 Command并包含一个默认构造函数:

public class CommandProcessor<T> : ICommandProcessor<T> where T : Command, new()

Command type 本身也定义了一个默认构造函数,它实现了一个接口(interface),ICommand .该接口(interface)包含一个方法,该方法要求输入参数的类型为 T :

void Process(T command);

所以我希望我能够定义一个类:

public class SpecificCommandProcessor : CommandProcessor<SpecificCommand>

它会起作用,因为 SpecificCommand继承自 Command并且还提供了默认构造函数。

到目前为止一切都很好。

但带有 C# 4.5 的 Visual Studio 2013 不会编译以下行:

CommandProcessor<Command> test = new SpecificCommandProcessor();

说它不能将源类型转换为目标类型。

这意味着我也不能执行以下操作:

List<CommandProcessor<Command>> myList = new List<CommandProcessor<Command>>;
var toAdd = new SpecificCommandProcessor();
myList.Add(toAdd);

我试过直接转换和安全转换,但编译器都不接受。然而很明显SpecificCommandProcessor实际上是 CommandProcessor<Command> .

我在这里错过了什么?

最佳答案

SpecificCommandProcessor不是 CommandProcessor<Command> , 这是一个 CommandProcessor<SpecificCommand> - 而那些东西是不同的。

例如,List<Animal>List<Sheep> (具有明显的继承性)。

List<Animal> animals = new List<Sheep>(); // if this were legal
animals.Add(new Wolf());                  // what should this do?

您可以做的是利用 C# 中的通用接口(interface)协变和逆变。例如,IEnumerable<T>是协变的,这意味着:

IEnumerable<Animal> animals = new List<Sheep>();

将实际工作。那是因为事后绝对没有办法向 IEnumerable 添加项目,您只能从中获取项目,而您将获得的项目肯定是 Animal 的实例。 . 它实际上是使用 IEnumerable<out T> 定义的, 其中out意味着结果将仅用作接口(interface)的输出,因此如果它至少是 T 或任何继承者,则该值是可以的。

您可能需要做的是创建一个协变接口(interface)

public interface ICommandProcessor<out T> where T : Command, new(){}

并让 CommandProcessor 实现它:

public class CommandProcessor<T>:ICommandProcessor<T> where T : Command, new(){}

在那种情况下,代码:

List<ICommandProcessor<Command>> myList = new List<ICommandProcessor<Command>>();
var toAdd = new SpecificCommandProcessor();
myList.Add(toAdd);

编译并工作(前提是这些类确实遵守协方差 promise )

关于c# - 参数类型不可分配给参数类型,它应该是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33778444/

相关文章:

java - 如何使用变量中提供的类型使用 GSON.fromJson ?

java - 在派生类的泛型对象上调用基方法

java - 使用泛型类而不定义类型时不会出错

c# - 通用类型。没有装箱转换或类型参数转换

c# - 不是有效的 Win32 应用程序

c# - 从 XmlNode 中删除子节点

c# - 如何运行Kinect SDK 中提供的C# SkeletalViewer 示例?

c# - 这是状态消息显示的最佳方式吗?

c# - 无法连接到任何指定的 MySQL 主机。 <添加名称 ="MySqlSiteMapProvider"

c# - 使用动态类型调用泛型扩展方法