2

我有一个特殊的对象,它包含一个对象列表和列表的一堆附带属性。

我有一个函数可以将项目注入我的特殊对象的列表部分。该函数取决于列表附带的属性,因此我选择创建一个包含属性和列表的新对象。

问题 1:在函数开始注入项目之前,谁负责确保 List 不为空?

  1. 调用者是否应该创建一个新列表并将其传递给函数?

  2. 不管传入的对象的状态如何,被调用者是否应该创建一个新列表并将其分配给对象?

  3. 函数是否应该设计为接收对象并返回一个新列表而不修改对象,让调用者将返回的列表分配给它的特殊对象?

或者......还有其他我没有考虑过的选择吗?

相关问题 2:鉴于我的设计需要 List 附带的属性,我应该选择创建一个同时包含属性和 List 的新类,还是应该创建一个包含其他属性的 List 子类?

4

2 回答 2

3

简而言之,从概念上讲,包含列表的对象负责拥有存储数据的有效方法,这意味着它应该负责在需要时实例化其列表。

如果对象被设计为表示对象的集合,那么它负责维护它在内部实际使用来存储它们的任何内容,除非目标的一部分是让新对象成为多种类型集合的“包装器”,允许基于内部使用的集合类型进行行为定制。

考虑一个列表。它在内部使用一个数组来存储数据,并根据需要处理所述数组的大小调整以存储新对象。您不必了解列表;从概念上讲,它是一个有序的索引集合,允许插入和删除元素。它可以用链表、红黑树或其他任何东西来实现;这些会对性能和复杂性产生影响。

回到正题。您的对象应该是具有附加属性的列表,应该隐藏其内部数据结构。用户不需要知道那里有一个 List 来保存元素。这意味着您的对象应该知道如何实例化它自己的内部数据结构,并公开调用者用来注入新元素的方法,这些新元素作用于内部列表。

一个例外是“包装器”,它添加了可以应用于任何其他类子集的新功能,并且允许用户指定新的类应该在特定用途中“包装”哪个类是很重要的。一个例子是 BlockingCollection。它增加了阻止正在对集合执行某些并发操作的线程的能力,直到它有效且安全地执行所述操作(例如,如果集合为空,则尝试从 BlockingCollection 获取项目的线程将被阻止,直到另一个线程添加一些东西)。创建时,可以指定 BlockingCollection 使用 IProducerConsumerCollection 接口的特定实现;很可能是同一命名空间中的内置“并发”集合之一,例如 ConcurrentBag、ConcurrentQueue 或 ConcurrentDictionary。即使在这种情况下,也有一个“默认”选项;您可以在不指定要使用的内部 Concurrent 结构的情况下实例化 BlockingCollection 对象,并且该对象将默认为 ConcurrentQueue。

于 2012-04-20T18:22:31.867 回答
2

假设您的列表是您的类实例的字段/成员,我建议new在类的构造函数中设置列表。

public class SpecialObject
{
    List<something> myList;
    public SpecialObject()
    {
        myList = new List<something>();
    }
}

或者在没有构造函数的情况下完成同样的事情:

public class SpecialObject
{
    List<something> myList = new List<something>();
}
于 2012-04-20T18:13:58.683 回答