这样做的目的是同步包含图形边缘的两个集合,发送方和接收方,以便在发生某些事情(删除边缘,添加边缘等)时通知双方。
为此,对集合的(反向)引用包含在集合中的元素中
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一起使用。