我定义了一个类 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/