简体   繁体   English

具有协变接口作为成员属性的协变接口

[英]Covariant interface with contravariant interface as member property

I have an interface which defines a reader and a writer for any IFoo. 我有一个接口,可以为任何IFoo定义一个读取器和一个写入器。

public interface IFoobarStore<out E>
 where E : class, IFoobar
{
    IFoobarReader<E> GetReader();
    IFoobarWriter<E> GetWriter();
}

IFoobarStore is covariant. IFoobarStore是协变的。 IFoobarStore interacts with any derived IFoo. IFoobarStore与任何派生的IFoo进行交互。 As such, any more derived IFoo should be assignable to a more derived IFoo type argument. 这样,任何更多派生的IFoo应该可以分配给一个更多派生的IFoo类型参数。

// DerivedFoobityStore.cs
public sealed class DerivedFoobityStore
 : IFoobarStore<MyFoobity>
{
    // implementation follows
}

If IFoobarStore were defined as being variant with IFoobarStore<E> instead of IFoobarStore<out E> , the following would produce compiler error CS0266. 如果IFoobarStore被定义为IFoobarStore<E>而不是IFoobarStore<out E>变体,则以下内容将产生编译器错误CS0266。

IFoobarStore<IFoo> myGenericStore = new DerivedFoobityStore();

The reader is defined as covariant as well. 读者也被定义为协变的。 It should allow reading derived IFoo objects from somewhere. 它应该允许从某处读取派生的IFoo对象。

using System.Collections.Generic;
public interface IFoobarReader<out E>
 where E : class, IFoo
{
    IEnumerable<E> GetAll();
    IEnumerable<E> GetBy(params object[] vars);
    E GetSingle(object uniqueIdentifier);
}

IFoobarWriter exposes members used for standard CRUD operations on any IFoo. IFoobarWriter公开任何IFoo上用于标准CRUD操作的成员。

public interface IFoobarWriter<in E>
 where E : class, IFoo
{
    void Add(E foo);
    int Delete(E foo);
    E Update(E foo);
}

Since every operation has a single argument of type E (any class derived from IFoo), IFoobarWriter must be flagged as contravariant. 由于每个操作都有一个类型E(从IFoo派生的任何类)的单个参数,因此必须将IFoobarWriter标记为变量。

When I compile my code I receive this error: 当我编译代码时,我收到此错误:

Invalid variance: The type parameter 'E' must be contravariantly valid on 'IFoobarStore<E>.GetWriter()'. 'E' is covariant.

How can I better refactor this code so it compiles successfully? 如何更好地重构此代码,使其成功编译?

For the moment I got around it by refactoring IFoobarWriter to work with an object instead of an IFoo. 目前,我通过重构IFoobarWriter以使用对象而不是IFoo来解决它。

public interface IFoobarWriter<out E>
 where E : class, IFoo
{
    void Add(object foo);
    int Delete(object foo);
    object Update(object foo);
}

This renders the basic premise of IFoobarWriter obsolete. 这使得IFoobarWriter的基本前提已过时。

The solution was to remove E as an acceptable argument for instance member methods of IFoobarWriter. 解决方案是删除E作为IFoobarWriter实例成员方法的可接受参数。

public interface IFoobarWriter<out E>
 where E : class, IFoo
{
    void Add(IFoo foo);
    int Delete(IFoo foo);
    object Update(IFoo foo);
}

By having Add, Delete, and Update accept IFoo they effectively limit the types they can work on (as opposed to setting the argument to object ) well enough for certain business requirements. 通过使Add,Delete和Update接受IFoo它们可以有效地限制它们可以处理的类型(与将参数设置为object ),足以满足某些业务需求。

Having the type parameter E for IFoobarWriter remain covariant allows it to remain a part of the IFoobarStore interface. 使IFoobarWriter的类型参数E保持协变,使其可以保留为IFoobarStore接口的一部分。

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

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