简体   繁体   English

派生接口之间没有隐式引用转换

[英]No implicit reference conversion between derived interfaces

The goal目标

Constructing a concrete object implementing ICoolbag and only being able to store ICoolBagGrocery instead of any type of grocery with IGrocery .构造一个具体的 object 实现ICoolbag并且只能存储ICoolBagGrocery而不是任何类型的杂货IGrocery

The problem问题

The implementation below results in the following error:下面的实现会导致以下错误:

The type 'SolidDistribution.Core.Bag.CoolBag.ICoolBag' cannot be used as type parameter 'T' 
in the generic type or method 'IBagStorage<T>'. There is no implicit reference conversion from
 'SolidDistribution.Core.Bag.CoolBag.ICoolBag' to 'SolidDistribution.Core.Bag.IBag<SolidDistribution.Core.IGrocery>'.

Implementation执行

Bag

// A bag that can only hold coolbag groceries.
public interface ICoolBag : IBag<ICoolBagGrocery> { }

// a bag that can hold any type of grocery.
public interface IBag<T> : IGroceryStorage<T> where T : IGrocery { }

Storage贮存

// A storage that can store any type of grocery.
public interface IGroceryStorage<T> : IStorage<T> where T : IGrocery { }

// A storage that can store any type of bag.
public interface IBagStorage<T> : IStorage<T> where T : IBag<IGrocery> { }

// Base storage interface.
public interface IStorage<T> { }

Grocery杂货店

// A grocery that can only be stored in a coolbag.
public interface ICoolBagGrocery : IGrocery { }

// Base grocery interface.
public interface IGrocery { }

Box盒子

// A box with a bag that can only hold coolbag groceries.
public interface ICoolBox : IBoxWithBag<ICoolBag> { }

// Base box with bag storage interface.
public interface IBoxWithBag<T> : IBox, IBagStorage<T> where T : IBag<IGrocery> { }

// Base box interface.
public interface IBox { }

Note笔记

Changing ICoolbag to use IGrocery instead of ICoolBagGrocery like so: ( public interface ICoolBag: IBag<IGrocery> { } ) fixes the error, but at the same time enables the ability to put any type of grocery in a coolbag.ICoolbag更改为使用IGrocery而不是ICoolBagGrocery ,如下所示:( public interface ICoolBag: IBag<IGrocery> { } ) 修复了错误,但同时能够将任何类型的杂货放入冷藏袋中。 Which is obviously not supposed to happen:)这显然不应该发生:)

Your compilation error is because T is invariant in IBag<T> .您的编译错误是因为TIBag<T>中是不变的。

ICoolBag is-a IBag<ICoolBagGrocery> , but IBag<ICoolBagGrocery> is not a IBag<IGrocery> . ICoolBagIBag<ICoolBagGrocery> ,但IBag<ICoolBagGrocery>不是IBag<IGrocery>

If you were to make T covariant in IBag<T> (using out ), then IBag<ICoolBagGrocery> would be a IBag<IGrocery> :如果您要在IBag<T>中使T协变(使用out ),那么IBag<ICoolBagGrocery>将是IBag<IGrocery>

public interface IBag<out T> : IGroceryStorage<T> where T : IGrocery { }

However, this would place restrictions on your IBag<T> interface: properties of type T would not allow set , and methods could only use T as the return type, not an argument type.但是,这会对您的IBag<T>接口施加限制:类型T的属性不允许set ,并且方法只能使用T作为返回类型,而不是参数类型。

For example:例如:

public interface IBag<out T> : IGroceryStorage<T> where T : IGrocery
{
    T SomeProperty { get; } // Allowed
    T AnotherProperty { get; set; } // Compilation error

    T SomeMethod(); // Allowed
    void AnotherMethod(T t); // Compilation error
}

Furthermore, the variance would rise through the inheritance hierarchy, meaning T would also need to be covariant in IGroceryStorage<T> and IStrorage<T> to make this valid.此外,方差将通过 inheritance 层次结构上升,这意味着T还需要在IGroceryStorage<T>IStrorage<T>中是协变的,以使其有效。

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

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