为什么在这种情况下需要界面协方差?

时间:2018-10-01 13:36:12

标签: c# generics covariance contravariance

我正在根据公共通用服务制作一个公共动作过滤器,以跨多个相似项目执行特定任务。

结构

  1. 基本过滤器-包含逻辑并在构造函数中接受服务参数:

    public abstract class BaseFilter
    {
        ...
        public BaseFilter(IService<IEntity> service)
        ...
    }
    
  2. 通用服务接口public interface IService<TEntity>
  3. 基本实体public class BaseEntity : IEntity
  4. 具体实体public class ConcreteEntity : BaseEntity
  5. 具体过滤器

    public class ConcreteFilter : BaseFilter
    {
        public ConcreteFilter(IService<ConcreteEntity> service) : base(service)
        {
        }
    }
    

这是基本的解决方案结构-服务和基础结构的公共层,然后通常使用特定于平台的类(在示例中为ConcreteFilter)派生,以将特定于平台的实体作为通用参数传递。

问题

以上内容无法编译:

Argument 1: cannot convert from 'Service<ConcreteEntity>' to 'Service<IEntity>'

我知道我可以使用协变服务界面对其进行修复:

public class IService<out TEntity>

但是我想避免这种情况。在此平台(我们称为 ConcretePlatform )中,通用参数始终为ConcreteEntity,因为它的接线方式类似于容器中的接线。我不想将通用参数限制在外部位置中,因为我有接受TEntity的重载。据我所知,C#已经在编译时检查了给定类型是否实现IEntity,这意味着它是类型安全的。我无法真正预见到问题,但即使有可能也会发生-我对运行时异常完全满意,因为这是依赖关系接线,除非有重大问题,否则它不会在生产中滑倒-主要的开发者监督。

一种可能的解决方法是改为使用IEntity作为参数类型,然后在每个方法中强制转换为TEntity,但是此强制转换是完全多余的。

想法

  1. 我的主张/理解是否有误?如果是这样,请说明如何以及为什么。
  2. 我想避免co / contra差异,因为如果我尝试以某种方式混合基本类型和派生类型,这应该是相关的,这根本不是我正在做的事情。此外,不可避免地会导致样板铸造。

0 个答案:

没有答案