派生接口之间没有隐式引用转换
No implicit reference conversion between derived interfaces
目标
构建一个实现 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> { }
) 修复了错误,但同时启用了将任何类型的杂货放入冷藏袋的能力。这显然不应该发生:)
你的编译错误是因为T
在IBag<T>
中是不变的。
ICoolBag
是一个 IBag<ICoolBagGrocery>
,但是 IBag<ICoolBagGrocery>
是 不是 一个 IBag<IGrocery>
.
如果要在 IBag<T>
中使 T
协变 (使用 out
),那么 IBag<ICoolBagGrocery>
将是IBag<IGrocery>
:
public interface IBag<out T> : IGroceryStorage<T> where T : IGrocery { }
但是,这会对您的 IBag<T>
接口施加限制:T
类型的属性不允许 set
,并且方法只能使用 T
作为 return类型,不是参数类型。
例如:
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>
中是协变的才能使其有效。
目标
构建一个实现 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> { }
) 修复了错误,但同时启用了将任何类型的杂货放入冷藏袋的能力。这显然不应该发生:)
你的编译错误是因为T
在IBag<T>
中是不变的。
ICoolBag
是一个 IBag<ICoolBagGrocery>
,但是 IBag<ICoolBagGrocery>
是 不是 一个 IBag<IGrocery>
.
如果要在 IBag<T>
中使 T
协变 (使用 out
),那么 IBag<ICoolBagGrocery>
将是IBag<IGrocery>
:
public interface IBag<out T> : IGroceryStorage<T> where T : IGrocery { }
但是,这会对您的 IBag<T>
接口施加限制:T
类型的属性不允许 set
,并且方法只能使用 T
作为 return类型,不是参数类型。
例如:
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>
中是协变的才能使其有效。