在对象中初始化集合?

时间:2008-12-08 19:04:11

标签: c# .net oop

如果对象具有属于集合的属性,那么对象是应该创建集合对象还是让使用者检查null?我知道消费者不应该假设,只是想知道大多数人是否创建了集合对象,如果它从未被添加到。

10 个答案:

答案 0 :(得分:7)

你也可以使用“Lazy initailizer”模式,其中集合未被初始化,直到(并且除非)有人访问它的属性getter ...这避免了在实例化父对象的情况下创建它的开销。出于其他目的,不需要收集...

   public class Division
    {
        private int divId;
        public int DivisionId { get; set; }

        private Collection<Employee> emps;
        public Collection<Employee> Employees
        { get {return emps?? (emps = new Collection<Employee>(DivisionId));}} 
    }
编辑:这个实现模式通常不是线程安全的......在第一个线程完成修改之前,emps可以被两个不同的线程读取为null。在这种情况下,它可能无关紧要,因为DivisionId是不可变的,虽然两个线程都会得到不同的集合,但它们都是有效的。因此,当第二个线程掠过时,emps将是一个有效的集合。 '可能'是因为第一个线程可能在第二个线程重置之前开始使用emps。这不是线程安全的。 Jon SKeet的另一个稍微复杂的实现是线程安全的(请参阅This article on SIngletons了解他如何解决此问题的示例/讨论。

答案 1 :(得分:3)

这取决于您与API和用户之间的合同。

就个人而言,我喜欢一个使Object管理其集合的合同,即在创建时实例化它们,并确保它们不能通过setter设置为null - 可能通过提供管理集合的方法而不是设置集合本身。

即addFoo(Foo toAdd)而不是setFooSet(Set set),等等。

但这取决于你。

答案 2 :(得分:2)

我通常会创建集合,然后提供从内部集合添加/删除项目的方法,而不是让类的使用者担心检查null。这也使您能够更好地控制集合中发生的事情。最终它取决于它的用途,但最有可能的是,如果你的类有一个集合,那么这个集合的消费者不仅可以拥有这些对象的集合。否则,为什么他们会使用你的班级?

答案 3 :(得分:2)

虽然我在这里所说的并不是通用的,但我认为集合最适合作为私有属性,应该通过对象本身的公共方法来访问。因此,对象负责根据需要创建和销毁它们。这样,就无法从外部代码将其设置为null。

答案 4 :(得分:2)

我更喜欢在实例化时创建集合,在包含对象中提供添加/删除方法,如果需要,还提供addAll / removeAll方法来添加和删除整个外部集合。我从不允许调用者访问或设置集合对象 - 但是,我可能会提供一个getter来返回集合的副本(可能是不可变的)。

我还有一个写时复制实现,它提供了一个不可变的包装视图,因为任何突变都会创建一个新的底层集合。

答案 5 :(得分:1)

我创建了一个空集合。当然,它的内存成本很低,但不足以引起人们的关注。

答案 6 :(得分:1)

IMO,这就是IEnumerable很好的地方。

就个人而言,我喜欢将我的'collection'属性初始化为空列表。

答案 7 :(得分:1)

如果集合是对象的固有部分,那么对象通常应该创建它(并且不允许用户将其设置为不同的集合实例)。

答案 8 :(得分:1)

我已经尝试了两种方式,当我发现我已经实现了它时,我通常很高兴。或者,您可以将消费者的实现隐藏在一组可以为您处理检查的方法背后。

答案 9 :(得分:0)

作为一般规则,我认为该对象应该创建集合并提供操作它的方法;添加/获取/删除。遵循此规则时,不应提供直接设置集合的方法。如果你想要一个方法,比如setSomeCollection(Collection someCollection),方法的实现不应该在对象中设置引用,而是将方法参数集合中的值复制到对象中的集合中;

public void setSomeCollection(Collection someCollection) {
   this.someCollection.clear();
   this.someCollection.addAll(someCollection);
}

您应该这样做,因此您的API的客户端无法访问您的类所维护的集合。如果他们这样做,他们可以在不使用你的类的对象的情况下操纵它,并违反你的班级保证的约束。

如果提供吸气剂,情况也是如此;您应该返回内部集合的副本或其只读版本。 Apache commons-collections和google-collections提供了在集合中创建不可变包装器的方法,以及java.util包中随Java一起提供的方法。 java.util.Collections.unmodifiable *