我在用C#编写的项目中跟踪遗留代码。
我找到以下代码:
public class FooCollection : Collection<IFoo> {};
我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。
为什么不直接使用内置集合(array
,List<T>
,Dictionary<K,V>
,...)
Collection<T>
中使用的数据结构是什么?阵列?或链表?
答案 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>
类)。
继承的优势在于您可以决定覆盖某些方法,并以您认为更适合您需求的方式处理它们,或者根据您的情况T
(IFoo
类型处理它们)。
同样,您也可以决定扩展您的API,以便支持您认为适合您情况的其他一些功能。
例如,如果你的课程IFoo
看起来像这样:
public interface IFoo
{
int a;
int b;
}
在派生类中,您可以向Remove添加一个类似于:
的重载public bool Remove(int a, int b )...
它会删除所有具有a
和b
答案 2 :(得分:1)
我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。
我永远不会。我个人认为Collection
课程根本没用。我还没有找到它的用途。
该类型的主要问题之一是大多数方法都不是虚拟的。唯一的虚拟方法是ClearItems
,InsertItem
,RemoveItem
和SetItem
(以及Equals
,GetHashCode
和{{1}来自ToString
)。其余的方法/属性不是虚拟的,因此无法覆盖。这意味着您可以稍微改变添加/插入/删除项目的语义,但这就是全部。
Object
中使用的数据结构是什么?
在内部,它由Collection<T>
支持。
为什么不直接使用内置集合(
List<T>
,array
,List<T>
,...)
几乎在所有情况下你都会这样做。虽然偶尔会有一些实际上想要创建全新集合类型的实例,但我从未发现Dictionary<K,V>
在创建此类自定义集合时有用的用法。通常,最好根据集合可以实现的内容实现Collection<T>
命名空间中的某些接口,并且如果它只是现有集合的扩展,则可以选择使用其他集合作为实例字段来组合类型。
答案 3 :(得分:1)
我不明白为什么(以及何时)我们需要像这样创建我们自己的Collection类。
实现自定义Collection<T>
的主要用例之一是序列化。
如果要自定义集合的序列化方式(for example to XML, using XmlSerializable
),可以创建自定义集合类并在其上实现IXmlSerializable
。然后,您可以通过操作该接口的Read
和Write
方法来更改如何读取或写入集合。
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>
我不喜欢将这个集合与这样的序列化相结合,但有时这是一种有效的方法。