【问题标题】:.NET - Collections and inheritance.NET - 集合和继承
【发布时间】:2012-01-18 01:08:12
【问题描述】:

我有三个班级,有共同的父母。假设父母是动物,孩子是狗,猫和鹦鹉。

我有一个可观察的集合,其中包含用户正在使用的动物集合。集合包含所有相同类型的动物 - 用户要么只与所有狗或所有猫或所有鹦鹉一起工作。

所以我声明了ObservableCollection<Animal>animals 并根据用户的选择我想将属性animals 的内容更改为ObservableCollection<Dog>ObservableCollection<Cat>ObservableCollection<PArrot>。因此,用户当前是否与狗或猫一起工作并不重要,但他可以选择动物的所有共同行为。

但它不起作用。我似乎无法将ObservableCollection<Cat> 分配给ObservableCollection<animal> 类型的属性。我认为它应该可以工作,因为动物是猫的超类型,所以我可以像往常一样将猫分配给动物变量。

为什么我不能这样做,我该如何解决这个问题?

【问题讨论】:

    标签: c# .net collections observablecollection


    【解决方案1】:

    您必须将这些集合键入为IEnumerable<T>,而不是使用ObservableCollection,因为ObservableCollection 不支持类型协变。任何允许您添加元素的集合都不会支持这种类型的继承。要了解原因,请考虑这个假设的代码(它编译)

    List<object> myObjects = new List<string>();
    

    你会认为这没问题,但看看如果你写下以下内容会发生什么:

    myObjects.Add(new Dog());
    

    myObjects 被声明为一个对象列表,所以上面的代码可以编译,但在运行时事情会爆炸,因为在幕后,myObjects 被实例化为只保存字符串。

    【讨论】:

    • 没有常规集合类型支持协方差; a: 不可能是一个带有 Add 和一个获取值的机制的集合类型支持变体, b: 只有接口和委托支持 4.0 风格的变体, 意思是:IEnumerable&lt;out T&gt;,但不是课程本身。
    • 我使用的是 C# 4.0。我绑定到这个集合,所以我需要使用 ObservableCollection。这可能吗?
    • @Marc - 我都知道 - 你能告诉我我的答案中的哪一部分暗示了其他内容,以便我更清楚吗?
    • 这将是你的忍者编辑之前的一点,它不那么明确;p
    • @Marc - 我想它已经被历史遗忘了 :) - 谢谢你打电话给我
    【解决方案2】:

    将其设为接口,并使用 co-variance

    interface ObservableCollection <out T>
    {
    
    }
    

    【讨论】:

      【解决方案3】:

      它不起作用的一个原因:如果它确实起作用,您可能会遇到无意义的情况:

      ObservableCollection<Animal> animals = new ObservableCollection<Dog>();
      animals.Add(new Cat()); // cat is an animal, after all
      

      另一个原因是ObservableCollection&lt;Dog&gt; 根本不是这种情况继承 ObservableCollection&lt;Animal&gt; - 它们只是ObservableCollection&lt;&gt; 的不同(并行)封闭泛型类型。

      允许的是,一些带有“out only”API(例如IEnumerable&lt;T&gt;)的接口可以是协变的,所以如果你只需要迭代它们,你可以拥有:

      IEnumerable<Animal> animals = new ObservableCollection<Dog>();
      

      (大概是在其他地方添加狗)

      另一种方法是使用非通用 API:

      IList animals = new ObservableCollection<Dog>();
      

      【讨论】:

        【解决方案4】:

        如果你不需要,不要用协方差过度复杂化它。 您应该创建 ObservableCollection&lt;Animal&gt;,无论您是用 Cats、Dogs 还是 Parrots 填充它,因为您不使用任何子类功能。

        你没有提到你为什么使用 ObervableCollection,但是如果你不观察它并且不关心列表更改的通知,你不妨转换它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-12-02
          • 1970-01-01
          • 2012-01-11
          • 1970-01-01
          • 1970-01-01
          • 2012-03-14
          • 1970-01-01
          相关资源
          最近更新 更多