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