Yng*_*sen 9 c# generics collections hashset
为什么我在以下代码中遇到编译错误(请参阅注释行)?
    public void Test()
    {
        HashSet<HashSet<Animal>> setWithSets = new HashSet<HashSet<Animal>>();
        HashSet<Cat> cats = new HashSet<Cat>();
        setWithSets.Add(cats); // Compile error
    }
    private class Animal { }
    private class Cat : Animal { }
VS2012给了我两个错误,第一个错误:
我的问题是:为什么我不能在"setWithSets"中添加"cats"?
ken*_*ken 10
为了更好地理解为什么不允许这样做,请考虑以下程序.
该行setOfSets.First().Add(new Dog());是编译器可以接受的,因为动物集合肯定可以保存一个实例Dog.问题是集合中的第一个动物集合是Cat实例的集合,并Dog没有扩展Cat.
class Animal { }
class Cat : Animal { }
class Dog : Animal { }
class Program {
    static void Main(string[] args) {
        // This is a collection of collections of animals.
        HashSet<HashSet<Animal>> setOfSets = new HashSet<HashSet<Animal>>();
        // Here, we add a collection of cats to that collection.
        HashSet<Cat> cats = new HashSet<Cat>();
        setOfSets.Add(cats);
        // And here, we add a dog to the collection of cats. Sorry, kitty!
        setOfSets.First().Add(new Dog());
    }
}
即使Cat从导出Animal,这是不正确的,HashSet<Cat>从派生HashSet<Animal>.(唯一的基类HashSet<Anything>是object类.)
要获得所需的行为,HashSet<T>泛型类型在其类型参数中需要是协变的T.但事实并非如此,原因有两个:
HashSet<>是一个班级.HashSet<>,还可以添加它(并做其他事情).因此,协方差在逻辑上是不可能的.或者,人们可以将a HashSet<Cat>视为a HashSet<Animal>,然后添加一个Dog.但是一组猫不允许狗.如果您改为HashSet<T>例如IReadOnlyCollection<T>(参见.NET 4.5 文档:IReadOnlyCollection<out T>接口),事情会起作用,因为后一种类型(1)是一个接口,(2)只允许读取,而(3)因此预先标记"我是T"该类型的作者决定适用的协变".
| 归档时间: | 
 | 
| 查看次数: | 1448 次 | 
| 最近记录: |