简体   繁体   English

泛型中的多态 - 传递继承对象时编译错误(无法隐式转换类型)

[英]Polymorphism in generics - compile error when passing inherited object (Cannot implicitly convert type)

The following code does not compile: 以下代码无法编译:

protected override ITaskScheduleAlgorithm<CollectionTask, ICoordinationExecutionService<CollectionTask>> GetAlgorithm()
{
    return new SimpleTaskScheduleAlgorithm<CollectionTask, WorkerServiceConfiguration>();
}

The error is: 错误是:

Cannot implicitly convert type... 无法隐式转换类型...

The types that could not be converted: 无法转换的类型:

WorkerServiceConfiguration → ICoordinationExecutionService WorkerServiceConfiguration→ICoordinationExecutionService

While the class WorkerServiceConfiguration inherits from ICoordinationExecutionService: 而WorkerServiceConfiguration类继承自 ICoordinationExecutionService:

public class WorkerServiceConfiguration : AbstractServiceConfiguration<CollectionTask>
{
...
}

public abstract class AbstractServiceConfiguration<TTask> : ICoordinationExecutionService<TTask>
{
...
}

Any idea why it's happening and how it can be resolved? 知道它为什么会发生以及如何解决它?

You should do like this 你应该这样做

protected override ITaskScheduleAlgorithm<CollectionTask, ICoordinationExecutionService<CollectionTask>> GetAlgorithm()
{
    return new SimpleTaskScheduleAlgorithm<CollectionTask, ICoordinationExecutionService<CollectionTask>>();
}

Then you can use WorkerServiceConfiguration type objects 然后,您可以使用WorkerServiceConfiguration类型对象

I think you have too many layers of generics and it's getting confusing. 我认为你有太多的泛型,它会让人感到困惑。 The actual answer is at the bottom, but first a digression to explain the problem... 实际的答案是在底部,但首先是一个解释问题的题外话......

You're correct that WorkerServiceConfiguration inherits from ICoordinationExecutionService. 你是正确的,WorkerServiceConfiguration继承自ICoordinationExecutionService。 That's why this code does work: 这就是为什么这段代码可行的原因:

protected ICoordinationExecutionService<CollectionTask> Test()
{
    return new WorkerServiceConfiguration();
}

But, you're not returning an ICoordinationService. 但是,您没有返回ICoordinationService。 You're returning an ITaskScheduleAlgorithm. 您正在返回ITaskScheduleAlgorithm。 Ignore the fact that the second one is an ICoordinationExecutionService, all you care about is this interface declaration. 忽略第二个是ICoordinationExecutionService的事实,你关心的只是这个接口声明。 In fact, for the sake of understanding the problem, let's simplify it further: 实际上,为了理解这个问题,让我们进一步简化它:

public interface ITaskScheduleAlgorithm<TType>
{
}

public class SimpleTaskScheduleAlgorithm<TType> : ITaskScheduleAlgorithm<TType>
{
}

public ITaskScheduleAlgorithm<object> GetAlgorithm()
{
    return new SimpleTaskScheduleAlgorithm<string>();
}

If you try running this simplified example, you'll get the exact same error. 如果您尝试运行此简化示例,您将得到完全相同的错误。 You know that string derives from object, so you would expect with polymorphism that this should work. 你知道这个字符串派生自object,所以你可以期待多态,这应该有用。 However, just because string derives from object does not mean SimpleTaskScheduleAlgorithm implements ITaskScheduleAlgorithm. 但是,仅仅因为字符串派生自对象并不意味着SimpleTaskScheduleAlgorithm实现了ITaskScheduleAlgorithm。 It depends on exactly what generic methods are implemented. 它完全取决于实现的泛型方法。 Think of the case of a List for example - even though string derives from object, you cannot add new objects to a List. 例如,可以考虑List的情况 - 即使string派生自object,也不能将新对象添加到List中。

In order to make this work, you need to add the 'out' keyword to your interface declaration. 为了使其工作,您需要在界面声明中添加'out'关键字。 For our simple case: 对于我们的简单案例:

public interface ITaskScheduleAlgorithm { } 公共接口ITaskScheduleAlgorithm {}

This indicates the interface is covariant (see covariance and contravariance in generics ). 这表明界面是协变的(参见泛型中的协方差和逆变 )。 Note that you can only make an interface covariant if it has no methods which accept an instance of the generic type as a parameter. 请注意,如果没有接受泛型类型实例作为参数的方法,则只能使接口协变。 So, the final answer for your problem is to add covariant support to your ITaskScheduleAlgorithm interface: 因此,您问题的最终答案是为您的ITaskScheduleAlgorithm接口添加协变支持:

public interface ITaskScheduleAlgorithm<TType, out TType2>
{
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM