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

时间:2021-03-10 15:48:05

标签: c# interface implicit-conversion derived-class

目标

构造一个实现 ICoolbag 的具体对象,并且只能存储 ICoolBagGrocery 而不是带有 IGrocery 的任何类型的杂货。

问题

下面的实现导致以下错误:

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>'.

实施

// 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 { }

存储

// 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> { }

杂货

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

// Base grocery interface.
public interface IGrocery { }

盒子

// 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 { }

注意

改变 ICoolbag 以使用 IGrocery 而不是 ICoolBagGrocery 像这样: (public interface ICoolBag : IBag<IGrocery> { }) 修复了错误,但同时能够将任何类型的杂货放入冷藏袋中。这显然不应该发生:)

1 个答案:

答案 0 :(得分:0)

您的编译错误是因为 TIBag<T> 中是不变的。

ICoolBagIBag<ICoolBagGrocery>,但 IBag<ICoolBagGrocery> notIBag<IGrocery>

如果您要在 T 中生成 IBag<T> 协变(使用 out),那么 IBag<ICoolBagGrocery> 将是 IBag<IGrocery> :

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

然而,这会限制您的 IBag<T> 接口:T 类型的属性不允许 set,并且方法只能使用 T 作为返回类型,不是参数类型。

例如:

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
}

此外,方差会在继承层次结构中上升,这意味着 T 还需要在 IGroceryStorage<T>IStrorage<T> 中协变以使其有效。

相关问题