问题描述
这是我的原始主题: C#通用继承和协变
仅在我的只读接口上,我希望继承起作用.
On just my read-only interfaces, I want inheritence to work.
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
Like this except where it compiles :-p
这就是我要工作的:
IReadOnlyCollection<String> s;
IReadOnlyCollection<Object> o = s;
推荐答案
这个问题似乎没有任何问题,所以我将回答几个问题.
There does not appear to be any question in this question, so I'll make up a few questions to answer.
假设我们有一些类型的 Fruit
和 Apple
和 Banana
具有明显的关系; Apple
是一种 Fruit
,以此类推.
Let's suppose we have some types Fruit
and Apple
and Banana
with the obvious relationships; Apple
is a kind of Fruit
, and so on.
协变转换是类型参数的可转换性暗示泛型类型的可转换性的转换.如果 Apple
可转换为 Fruit
,并且 Bowl< Apple>
可转换为 Bowl< Fruit>
,则 Bowl< T>
在T中是协变的.
A covariant conversion is one where the convertability of the type argument implies the convertibility of the generic type. If Apple
is convertible to Fruit
, and Bowl<Apple>
is convertible to Bowl<Fruit>
, then Bowl<T>
is covariant in T.
逆变转换是一种协变转换,它反转方向而不是保留方向.如果 Eater< Fruit>
可转换为 Eater< Apple>
,则 Eater< T>
在T中是互变的.
A contravariant conversion is a covariant conversion that reverses the direction instead of preserving it. If Eater<Fruit>
is convertible to Eater<Apple>
then Eater<T>
is contravariant in T.
协变量类型参数标记为 out
,而协变量类型参数标记为 in
.
Covariant type parameters are marked out
and contravariant type parameters are marked in
.
这旨在用作助记符:协变接口通常将类型参数显示在输出位置,而互变接口通常将类型参数显示在输入位置.
This is intended to be mnemonic: covariant interfaces typically have the type parameter appear in output positions and contravariant interfaces typeically have the type parameter appear in input positions.
在T中使 IReadOnlyCollection< T>
协变.将其标记为 out
.
Make IReadOnlyCollection<T>
covariant in T. Mark it out
.
delegate void Action<in T>(T t);
interface IFoo<in X>
{
void M(Action<X> action);
}
因为它无效.让我们看看为什么.
Because it is not valid. Let's see why.
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"传递,这显然是错误的.
Follow the logic. This program passes an apple as the "this" of Banana.Peel()
, which is clearly wrong.
编译器知道这是可能发生的,因此不允许首先声明接口.
The compiler knows that this can happen, and so disallows the interface to be declared in the first place.
您应该先阅读有关该功能的设计和实现的文章.从底部开始;它们以相反的时间顺序列出:
You should start by reading my articles on the design and implementation of the feature. Start from the bottom; they are listed in reverse chronological order:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance + and + contravariance/
如果您仍然有问题,则应在此处发布实际上包含问题的问题,而不是让人们猜测问题的实质.
If you still have a question then you should post questions here that actually contain questions, instead of making people guess what the question really is.
这篇关于C#通用继承和协方差第2部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!