ICollection <T> не Ковариант?
Цель этого состоит в том, чтобы синхронизировать две коллекции, на стороне отправителя и на стороне получателя, содержащие ребро графа, так, чтобы когда что-то происходило (удаление ребра, добавление ребра и т. Д.), Обе стороны получали уведомление.
Для этого (обратные) ссылки на коллекции были включены в элемент коллекции
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;
}
Удаление (Disconnect) было в порядке, но проблема возникла при создании:
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.