我一直在尝试找出如何在C#中获得以下Java代码的等效项(命令是功能接口)。
public interface Executor<C extends Command> {
void execute(final C command) throws Exception;
}
我目前在Java版本中设计代码的方式,类型C扩展Command是必要的,据我所知,Command是用C#的协方差来处理的。
但是根据C#文档,由于“ The type is used only as a return type of interface methods and not used as a type of method arguments”之类的以下内容将不起作用
interface IExecutor<out Command>
{
void Execute(Command command);
}
是否有一种方法可以指定方法的参数类型必须与C#中的接口类型协变量?
我是C#的新手,所以可能是XY问题,但到目前为止我还没有找到可行的解决方案。
答案 0 :(得分:2)
我认为您追求的是generic type constraint:
interface IExecutor<T> where T : Command
{
void Execute(T command);
}
这表示T
可以是任何东西,只要它扩展了Command
类。
Covariance与此有点不同,它涉及不同类型(数组,泛型和委托)之间的转换。
例如,IEnumerable声明为IEnumerable<out T> { ... }
,这使其成为协变变量。这是对编译器的保证,即您将永远只提取IEnumerable<T>
中的项目 out ,而永远不会将它们放入。
这意味着可以安全地编写例如
IEnumerable<object> x = new List<string>();
由于您只能从IEnumerable
中取出字符串,因此可以假装它们都是对象。如果允许您将项目放入IEnumerable
,则可以将任何旧对象放入仅允许string
的集合中,这是不安全的。
以您的示例为例,因为您只将Commands
放入IExecutor
中,因此可以将其声明为反变量:
interface IExecutor<in T> where T : Command
{
void Execute(T command);
}
这可以让您写:
IExecutor<Command> baseExecutor = ....;
IExecutor<SpecialisedCommand> executor = baseExecutor;
这是安全的,因为您已经向编译器保证IExecutor
上的方法将只接受Command
对象,并且永远不会返回它们。