c# – ICollection不协变?

前端之家收集整理的这篇文章主要介绍了c# – ICollection不协变?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这样做的目的是同步两个集合,发送方和接收方,包含一个图形边缘,这样当发生某些事情(删除边缘,添加边缘等)时,通知双方.

为了做到这一点,对集合的(back-)引用被包含在集合中的元素中

class EdgeBase {
    EdgeBase(ICollection<EdgeBase> rCol,ICollection<EdgeBase> sCol)     
    { RecvCol=rCol;  SendCol=sCol; }      
    ICollection<EdgeBase> RecvCol;      
    ICollection<EdgeBase> SendCol;       
    public virtual void Disconnect() // Synchronized deletion         
    { RecvCol.Remove(this);  SendCol.Remove(this); }                 
}         
class Edge : EdgeBase {       
    Edge(ICollection<EdgeBase> rCol,ICollection<EdgeBase> sCol)     
    : base(rCol,sCol) {}
    int Weight;     
}

删除(断开连接)是确定,但问题发生在创建期间:

HashSet<Edge> receiverSet,senderSet;
var edge = new Edge(receiverSet,senderSet); // Can't convert Edge to EdgeBase!

虽然Edge来自EdgeBase,但这是非法的.
(问题是Edge部分,而不是HashSet<>部分)

写了数百行后,我发现ICollection<>不像IEnumerable<>是协变的.

什么可以解决办法?

编辑:

如果我在上面写代码,而不是打破C#的协方差规则,那就是这样的:

public class EdgeBase<T,U>
    where T : ICollection<U<T>> // illegal
    where U : EdgeBase<T,U>    // legal,but introduces self-reference
{
    public EdgeBase(T recvCol,T sendCol) {...}
    protected T ReceiverCollection;
    protected T SenderCollection;
    public virtual void Disconnect() {...}
}

但这是非法的’U’不能与形式参数T一起使用.

解决方法

Eric Lippert said that C# will only support type-safe covariance and contravariance.如果你想到它,使ICollection协变不是类型安全的.

让我们说你有

ICollection<Dog> dogList = new List<Dog>();
ICollection<Mammal> mammalList = dogList; //illegal but for the sake of showing,do it
mammalList.Add(new Cat());

你的哺乳动物列表(实际上是一个dogList)现在将包含一只猫.

IEnumerable是协变的,因为你不能添加到它…你只能从它读取 – 反过来保留类型安全.

猜你在找的C#相关文章