- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这样做的目的是同步两个集合,发送端和接收端,包含一个图的边,这样当发生某些事情(删除边,添加边等)时,双方都会收到通知。
为此,对集合的(反向)引用包含在集合中的元素中
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 一起使用。
最佳答案
Eric Lippert said that C# will only support type-safe covariance and contravariance.如果你会想到它,制作ICollection
协变不是类型安全的。
假设你有
ICollection<Dog> dogList = new List<Dog>();
ICollection<Mammal> mammalList = dogList; //illegal but for the sake of showing, do it
mammalList.Add(new Cat());
你的 mammalList
(实际上是一个 dogList
)现在将包含一个 Cat
.
IEnumerable<T>
是协变的,因为你不能 Add
到它......你只能从它读取 - 这反过来又保留了类型安全。
关于c# - ICollection<T> 不是协变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16996626/
在我的设置中,我试图有一个界面 Table继承自 Map (因为它主要用作 map 的包装器)。两个类继承自 Table - 本地和全局。全局的将有一个可变的映射,而本地的将有一个只有本地条目的映射。
Rust Nomicon 有 an entire section on variance除了关于 Box 的这一小节,我或多或少地理解了这一点和 Vec在 T 上(共同)变体. Box and Vec
我是一名优秀的程序员,十分优秀!