这是我原来的主题: C# generic inheritance and covariance
仅在我的只读接口上,我希望继承工作。
public delegate Boolean EnumerateItemsDelegate<out ItemType>(ItemType item);
public interface IReadOnlyCollection<out ItemType>
{
Boolean ContainsItem(ItemType item);
Array CopyToArray();
void EnumerateItems(EnumerateItemsDelegate<ItemType> enumerateDelegate);
UInt32 Count { get; }
UInt32 Capacity { get; }
}
除此之外,它编译:-p
这就是我想要的工作:
IReadOnlyCollection<String> s;
IReadOnlyCollection<Object> o = s;
答案 0 :(得分:5)
这个问题似乎没有任何问题,所以我会回答几个问题。
什么是协变转换?
我们假设我们有一些类型Fruit
和Apple
以及Banana
具有明显的关系; Apple
是一种Fruit
,依此类推。
协变转换是类型参数的可转换性意味着泛型类型的可转换性的转换。如果Apple
可转换为Fruit
,而Bowl<Apple>
可转换为Bowl<Fruit>
,则Bowl<T>
在T中是协变的。
什么是逆变换?
逆变换是一种协变转换,反转方向而不是保留它。如果Eater<Fruit>
可转换为Eater<Apple>
,那么Eater<T>
在T中是逆变的。
如何将接口或委托标记为其类型参数中的协变或逆变?
协变类型参数标记为out
,逆变类型参数标记为in
。
这是助记符:协变接口通常在输出位置显示类型参数,而逆变接口通常在输入位置显示类型参数。
String
可转换为Object
。如何将IReadOnlyCollection<String>
转换为IReadOnlyCollection<Object>
?
在T.中设置IReadOnlyCollection<T>
协变。标记为out
。
请考虑以下代码:
delegate void Action<in T>(T t);
interface IFoo<in X>
{
void M(Action<X> action);
}
为什么编译器说这是无效的?
因为它无效。让我们看看为什么。
class Foo : IFoo<Fruit>
{
public void M(Action<Fruit> action)
{
action(new Apple()); // An apple is a fruit.
}
}
...
IFoo<Fruit> iff = new Foo();
IFoo<Banana> ifb = iff; // Contravariant!
ifb.M(banana => { banana.Peel(); });
遵循逻辑。该程序将苹果作为Banana.Peel()
的“this”传递,这显然是错误的。
编译器知道这可能发生,因此不允许首先声明接口。
如果我对方差有更多疑问,该怎么办?
您应该首先阅读有关该功能的设计和实现的文章。从底部开始;它们以反向时间顺序列出:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
如果你还有问题,那么你应该在这里发布实际上包含问题的问题,而不是让人们猜出问题究竟是什么。