如何公开一个集合属性? [英] How to expose a collection property?

查看:164
本文介绍了如何公开一个集合属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我每次创建一个对象,它有一个集合属性我来回走的最好的方式做到这一点?

Every time I create an object that has a collection property I go back and forth on the best way to do it?

  1. 在公共财产与一个getter的 返回对私有变量
  2. 明确get_ObjList和set_ObjList 返回并创造新的或克隆的方法 对象每次
  3. 明确get_ObjList一个返回 IEnumerator的和set_ObjList的 需要的IEnumerator
  1. public property with a getter that returns a reference to private variable
  2. explicit get_ObjList and set_ObjList methods that return and create new or cloned objects every time
  3. explicit get_ObjList that returns an IEnumerator and a set_ObjList that takes IEnumerator

这是否有所作为如果集合是一个数组(即objList.Clone())与一个列表?

Does it make a difference if the collection is an array (i.e., objList.Clone()) versus a List?

如果实际的集合返回作为参考是如此糟糕,因为它创造的依赖关系,那么为什么返回任何财产作为参考?任何时候你公开为基准那个孩子的内部,而不父知道被改变的子对象,除非孩子有一个改变财产的事件。是否有内存泄漏的危险?

If returning the actual collection as a reference is so bad because it creates dependencies, then why return any property as a reference? Anytime you expose an child object as a reference the internals of that child can be changed without the parent "knowing" unless the child has a property changed event. Is there a risk for memory leaks?

和,没有选择2和3打破序列化?这是一个catch 22或你有你有一个集合属性来实现自定义序列化随时随地?

And, don't options 2 and 3 break serialization? Is this a catch 22 or do you have to implement custom serialization anytime you have a collection property?

通用ReadOnlyCollection还似乎是一个很好的平衡用于一般用途。它包装一个IList,并限制对它的访问。也许这有助于内存泄漏和系列化。然而,它仍然有枚举关注

The generic ReadOnlyCollection seems like a nice compromise for general use. It wraps an IList and restricts access to it. Maybe this helps with memory leaks and serialization. However it still has enumeration concerns

也许这只是取决于。如果你不介意的集合被修改,那么就暴露出它作为一个公共存取超过每#1私有变量。如果你不希望其他程序来修改该集合,然后#2和/或#3更好。

Maybe it just depends. If you don't care that the collection is modified, then just expose it as a public accessor over a private variable per #1. If you don't want other programs to modify the collection then #2 and/or #3 is better.

隐性的问题是为什么要一种方法反复使用另一个,什么是安全,存储,系列化等方面的后果?

Implicit in the question is why should one method be used over another and what are the ramifications on security, memory, serialization, etc.?

推荐答案

您如何公开一个集合完全取决于用户如何打算与之交互。

How you expose a collection depends entirely on how users are intended to interact with it.

1)如果用户将被添加和从对象的集合删除项目,然后进行简单的get-只集合属性是最好的(选择#1从原来的问题):

1) If users will be adding and removing items from an object's collection, then a simple get-only collection property is best (option #1 from the original question):

private readonly Collection<T> myCollection_ = new ...;
public Collection<T> MyCollection {
  get { return this.myCollection_; }
}

本策略用于产品在WindowsForms和WPF 的ItemsControl 控件,用户添加和删除集合项目他们想要的控件来显示。这些控件公布的实际收集和利用回调或事件侦听器来跟踪项目。

This strategy is used for the Items collections on the WindowsForms and WPF ItemsControl controls, where users add and remove items they want the control to display. These controls publish the actual collection and use callbacks or event listeners to keep track of items.

WPF也暴露了一些可设置的集合,以允许用户显示他们控制的物品,如的ItemsControl 的ItemsSource 属性的集合C $ C>(#3选项从原来的问题)。然而,这不是一个普通的用例。

WPF also exposes some settable collections to allow users to display a collection of items they control, such as the ItemsSource property on ItemsControl (option #3 from the original question). However, this is not a common use case.


2)如果用户只能读取由对象保持的数据,那么你可以使用一个只读集合,如<一个href="http://stackoverflow.com/questions/35007/how-to-expose-a-collection-property#35065">Quibblesome建议:


2) If users will only be reading data maintained by the object, then you can use a readonly collection, as Quibblesome suggested:

private readonly List<T> myPrivateCollection_ = new ...;
private ReadOnlyCollection<T> myPrivateCollectionView_;
public ReadOnlyCollection<T> MyCollection {
  get {
    if( this.myPrivateCollectionView_ == null ) { /* lazily initialize view */ }
    return this.myPrivateCollectionView_;
  }
}

注意 ReadOnlyCollection还&LT; T&GT; 提供底层集合的实时取景,所以你只需要创建视图一次

Note that ReadOnlyCollection<T> provides a live view of the underlying collection, so you only need to create the view once.

如果内部集合不执行的IList&LT; T&GT; ,或者如果你想限制访问更高级的用户,则可以改为包通过接入到集合枚举:

If the internal collection does not implement IList<T>, or if you want to restrict access to more advanced users, you can instead wrap access to the collection through an enumerator:

public IEnumerable<T> MyCollection {
  get {
    foreach( T item in this.myPrivateCollection_ )
      yield return item;
  }
}

此方法很容易实现,也可以访问所有成员不暴露内部集合。但是,它需要收集保持unmodfied,因为如果你试图枚举集合已被修改后,首创置业集合类会抛出异常。如果底层集合很可能会改变,你可以创建一个轻包装,将枚举集合安全,或者返回集合的一个副本。

This approach is simple to implement and also provides access to all the members without exposing the internal collection. However, it does require that the collection remain unmodfied, as the BCL collection classes will throw an exception if you try to enumerate a collection after it has been modified. If the underlying collection is likely to change, you can either create a light wrapper that will enumerate the collection safely, or return a copy of the collection.


3)最后,如果你需要公开的数组,而不是更高级别的集合,那么你应该从原单问题,对其进行修改(选项#2返回数组prevent用户的副本):


3) Finally, if you need to expose arrays rather than higher-level collections, then you should return a copy of the array to prevent users from modifying it (option #2 from the orginal question):

private T[] myArray_;
public T[] GetMyArray( ) {
  T[] copy = new T[this.myArray_.Length];
  this.myArray_.CopyTo( copy, 0 );
  return copy;
  // Note: if you are using LINQ, calling the 'ToArray( )' 
  //  extension method will create a copy for you.
}

您应该不会对底层数组通过财产公开,因为你将不能够告诉当用户修改它。为了让修改数组,你可以添加相应的 SetMyArray(T []数组)的方法,或者使用自定义索引:

You should not expose the underlying array through a property, as you will not be able to tell when users modify it. To allow modifying the array, you can either add a corresponding SetMyArray( T[] array ) method, or use a custom indexer:

public T this[int index] {
  get { return this.myArray_[index]; }
  set {
    // TODO: validate new value; raise change event; etc.
    this.myArray_[index] = value;
  }
}

(当然,通过实现自定义索引器,你将复制的BCL类的工作:)

(of course, by implementing a custom indexer, you will be duplicating the work of the BCL classes :)

这篇关于如何公开一个集合属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆