ICollection <T> no Covariant?
El propósito de esto es sincronizar dos colecciones, lado del remitente y lado del receptor, que contienen un borde del gráfico, de modo que cuando algo sucede (eliminar borde, agregar borde, etc.) se notifique a ambos lados.
Para ello, se incluyeron (atrás) referencias a las colecciones en el elemento en colecciones.
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;
}
La eliminación (Desconectar) estuvo bien, pero el problema ocurrió durante la creación:
HashSet<Edge> receiverSet, senderSet;
var edge = new Edge(receiverSet, senderSet); // Can't convert Edge to EdgeBase!
A pesar de queEdge
se deriva deEdgeBase
, esto es ilegal. (El problema esEdge
parte, noHashSet<>
parte.)
Después de escribir cientos de líneas me enteréICollection<>
no es covariante como esIEnumerable<>
.
¿Qué podría ser una solución?
EDITAR:
Si escribiera el código anterior sin romper las reglas de covarianza de C #, habría sido así:
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() {...}
}
Pero esto es ilegal; 'U' no puede usarse con el parámetro formal T.