微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

派生接口之间没有隐式引用转换 实施注意

如何解决派生接口之间没有隐式引用转换 实施注意

目标

构造一个实现 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> { }) 修复了错误,但同时能够将任何类型的杂货放入冷藏袋中。这显然不应该发生:)

解决方法

您的编译错误是因为 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> 中协变以使其有效。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。