C#:对于收藏范例封装(C#: Encapsulation of for example colle

2019-07-31 10:44发布

我想知道其中哪些人会被认为是最干净的或者最好使用以及为什么。

其中一人暴露乘客,这让用户添加和删除等其他隐藏列表,并只让用户一一列举,并添加使用一种特殊的方法的列表。

实施例1

class Bus
{
    public IEnumerable<Person> Passengers { get { return passengers; } }
    private List<Passengers> passengers;

    public Bus()
    {
        passengers = new List<Passenger>();
    }

    public void AddPassenger(Passenger passenger)
    {
        passengers.Add(passenger);
    }
}

var bus = new Bus1();
bus.AddPassenger(new Passenger());
foreach(var passenger in bus.Passengers)
    Console.WriteLine(passenger);

实施例2

class Bus
{
    public List<Person> Passengers { get; private set; }

    public Bus()
    {
        Passengers = new List<Passenger>();
    }
}

var bus = new Bus();
bus.Passengers.Add(new Passenger());
foreach(var passenger in bus.Passengers)
    Console.WriteLine(passenger);

第一类我想说的是更好的封装。 而在这种情况下准确,这可能是更好的方法(因为你应该确保它留在公共汽车上空间等)。 但我想有可能是情况下,第二类可能是有用的呢? 就像如果类并不真正关心,只要它有一个上发生了什么名单。 你怎么看?

Answer 1:

在例如一个,有可能发生变异您的收藏。

考虑以下:

var passengers = (List<Passenger>)bus.Passengers;

// Now I have control of the list!
passengers.Add(...);
passengers.Remove(...);

为了解决这个问题,你可能会考虑这样的事情:

class Bus
{
  private List<Passenger> passengers;

  // Never expose the original collection
  public IEnumerable<Passenger> Passengers
  {
     get { return passengers.Select(p => p); }  
  }

  // Or expose the original collection as read only
  public ReadOnlyCollection<Passenger> ReadOnlyPassengers
  {
     get { return passengers.AsReadOnly(); }
  }

  public void AddPassenger(Passenger passenger)
  {
     passengers.Add(passenger);
  }
 }


Answer 2:

在大多数情况下,我会考虑例如2是可以接受的,基础类型是可扩展的和/或暴露某种形式的onAdded回调函数里/ onRemoved事件,这样你的内部类可以任意更改收集回应。

在这种情况下的List <T>,因为没有办法让全班知道,如果事情已经加入是不合适的。 相反,你应该使用一个集合,因为集合<T>类有几个虚拟成员(插入,删除,设置,清除),可以覆盖和触发器添加的事件通知包装类。

(你也必须意识到类的用户可以修改列表/集合中的项目,而不父类不了解它,所以请确保您不依赖于项目是不变的 - 除非它们是不可变的明显 - 或者你可以,如果你需要提供风格调用onChanged事件)。



Answer 3:

通过FxCop的运行您的实例和应该给你暴露的风险提示List<T>



Answer 4:

我会说这一切都归结到你的情况。 我通常会去选择2,因为它是最简单的, 除非你有一个企业之所以严格的控制添加到它。



Answer 5:

方案2是最简单的,但让其他类来添加/删除元素收集,这会非常危险。

我认为一个好的启发式是要考虑什么样的包装方法做。 如果您AddPassenger(或删除,或其他)方法简单地中继调用集合,然后我会去的简化版本。 如果您有将它们插入检查的元素,然后选择1基本上是不可避免的。 如果你有跟踪插入/删除的元素,你可以去任何一种方式。 对于选项2,你必须注册在收集事件得到通知,并与选项1,你必须为你想使用(例如,如果你想插入以及添加),所以我想在名单上的每个操作创建包装这取决于。



文章来源: C#: Encapsulation of for example collections