为什么以及何时从Collection <t> </t>继承

时间:2013-12-31 12:39:33

标签: c# data-structures collections

我在用C#编写的项目中跟踪遗留代码。

我找到以下代码:

public class FooCollection : Collection<IFoo> {};

我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。

为什么不直接使用内置集合(arrayList<T>Dictionary<K,V>,...)

Collection<T>中使用的数据结构是什么?阵列?或链表?

4 个答案:

答案 0 :(得分:5)

  

我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。

你真的不需要&#34;至;你可以直接使用Collection<IFoo>,但拥有一个特定的类可以帮助提高可读性。此外,它还允许您为此集合类型添加特定行为。此外,Collection<T>类允许通过覆盖虚方法重新定义大多数操作;这允许您自定义标准集合方法的行为。

  

为什么不使用内置集合(数组,列表,字典,...)

数组具有固定长度,因此您无法添加或删除项目;所以它并不是真的相同。 Dictionary<K,V>将值与键相关联,因此它的目的明显不同。只要您不需要自定义行为,就可以使用List<T>代替;此类不是为继承而设计的,因为它的方法是非虚拟的。

  

Collection中使用的数据结构是什么?阵列?或链表?

Collection<T>充当另一个IList<T>的包装器。默认情况下,它使用List<T>(基于数组),但您可以将任何其他IList<T>实现传递给构造函数,它将使用它。

答案 1 :(得分:4)

通过声明您继承Collection<T>类,您声明您的类是IS-A Collection<T>,意味着您已经实现了所有it's API(通过派生类或基于Collection<T>类)。

继承的优势在于您可以决定覆盖某些方法,并以您认为更适合您需求的方式处理它们,或者根据您的情况TIFoo类型处理它们)。

同样,您也可以决定扩展您的API,以便支持您认为适合您情况的其他一些功能。

例如,如果你的课程IFoo看起来像这样:

public interface IFoo
{
   int a;
   int b;
}

在派生类中,您可以向Remove添加一个类似于:

的重载
public bool Remove(int a, int b )...

它会删除所有具有ab

值的特定值的项目

答案 2 :(得分:1)

  

我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。

我永远不会。我个人认为Collection课程根本没用。我还没有找到它的用途。

该类型的主要问题之一是大多数方法都不是虚拟的。唯一的虚拟方法是ClearItemsInsertItemRemoveItemSetItem(以及EqualsGetHashCode和{{1}来自ToString)。其余的方法/属性不是虚拟的,因此无法覆盖。这意味着您可以稍微改变添加/插入/删除项目的语义,但这就是全部。

  

Object中使用的数据结构是什么?

在内部,它由Collection<T>支持。

  

为什么不直接使用内置集合(List<T>arrayList<T>,...)

几乎在所有情况下你都会这样做。虽然偶尔会有一些实际上想要创建全新集合类型的实例,但我从未发现Dictionary<K,V>在创建此类自定义集合时有用的用法。通常,最好根据集合可以实现的内容实现Collection<T>命名空间中的某些接口,并且如果它只是现有集合的扩展,则可以选择使用其他集合作为实例字段来组合类型。

答案 3 :(得分:1)

  

我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。

实现自定义Collection<T>的主要用例之一是序列化。

如果要自定义集合的序列化方式(for example to XML, using XmlSerializable),可以创建自定义集合类并在其上实现IXmlSerializable。然后,您可以通过操作该接口的ReadWrite方法来更改如何读取或写入集合。

class MyCollection : Collection<string>, IXmlSerializable
{
    public XmlSchema GetSchema()
    {
        return(null);
    }

    public void WriteXml(XmlWriter writer)
    {
        //// foreach (var item in Items)
            //// writer.Write...
    }

    public void ReadXml(XmlReader reader)
    {
        //// Items.Add(reader.Read...
    }
}

与在父类上实现IXmlSerializable相比,这在大多数情况下更为可取,因为它会导致整体代码更少并促进重用(您可以在多个位置重复使用相同的集合,并且它将在同一个序列中进行序列化只要你使用XmlSerializer来序列化它就可以了。)

由于外部系统要求集合中的每个元素生成一个XML节点,并附加了元素的索引,我最近才使用它。

最终结构看起来有点像这样:

<MyCollection>
  <Item1>first item</Item1>
  <Item2>second item</Item2>
  ...
</MyCollection>

我不喜欢将这个集合与这样的序列化相结合,但有时这是一种有效的方法。

相关问题