ICollection <T> не Ковариант?
Цель этого состоит в том, чтобы синхронизировать две коллекции, сторона отправителя и сторона получателя, содержащая ребро графа, так что когда что-то происходит (удаляем ребро, добавляем ребро и т. д.), обе стороны получают уведомление.
Для этого (обратные) ссылки на коллекции были включены в элемент коллекции
class EdgeBase {
EdgeBase(ICollection rCol, ICollection sCol)
{ RecvCol=rCol; SendCol=sCol; }
ICollection RecvCol;
ICollection SendCol;
public virtual void Disconnect() // Synchronized deletion
{ RecvCol.Remove(this); SendCol.Remove(this); }
}
class Edge : EdgeBase {
Edge(ICollection rCol, ICollection sCol)
: base(rCol, sCol) {}
int Weight;
}
Удаление (Disconnect) было в порядке, но проблема возникла при создании:
HashSet receiverSet, senderSet;
var edge = new Edge(receiverSet, senderSet); // Can't convert Edge to EdgeBase!
ХотяEdge
происходит отEdgeBase
это незаконно. (Проблема вEdge
часть, а неHashSet
часть.)
После написания сотен строк я узналICollection
не является ковариантным как есть.IEnumerable
Что может быть обходным путем?
РЕДАКТИРОВАТЬ:
Если бы я написал код выше, не нарушая C # 'Правила ковариации это было бы так:
public class EdgeBase
where T : ICollection // illegal
where U : EdgeBase // legal, but introduces self-reference
{
public EdgeBase(T recvCol, T sendCol) {...}
protected T ReceiverCollection;
protected T SenderCollection;
public virtual void Disconnect() {...}
}
Но это незаконно; 'U' Можно'не может использоваться с формальным параметром T.