Целью этого является синхронизация двух коллекций, стороне отправителя и получателя, содержащей край графика, так что когда что-то происходит (удаляем край, добавляем кромку и т.д.), обе стороны уведомляются.
Чтобы сделать это, обратные ссылки на коллекции были включены в элемент в коллекциях
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;
}
Deletion (Disconnect) было нормально, но проблема возникла во время создания:
HashSet<Edge> receiverSet, senderSet;
var edge = new Edge(receiverSet, senderSet); // Can't convert Edge to EdgeBase!
Хотя Edge
получен из EdgeBase
, это незаконно.
(Проблема состоит в Edge
part, not HashSet<>
part.)
После написания сотен строк, которые я обнаружил, ICollection<>
не является ковариантным, как IEnumerable<>
.
Что может быть обходным способом?
EDIT:
Если бы я написал код выше, не нарушая правила ковариации С#, это было бы так:
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.