c# practices How to expose a collection property?




c# getter setter shorthand (10)

Are immutable arrays possible in .NET?

ReadOnlyCollection<T> is probably what you are looking for. It doesn't have an Add() method.

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

  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

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?

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?

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

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) 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_; }
}

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 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) 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_;
  }
}

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

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;
  }
}

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) 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.
}

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;
  }
}

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


This really depends on what you mean by "add."

If you mean:

T[] array;
int i;
T value;
...
if (i >= 0 && i <= array.Length)
    array[i] = value;

Then, no, this does not create a new array, and is in-fact the fastest way to alter any kind of IList in .NET.

If, however, you're using something like ArrayList, List, Collection, etc. then calling the "Add" method may create a new array -- but they are smart about it, they don't just resize by 1 element, they grow geometrically, so if you're adding lots of values only every once in a while will it have to allocate a new array. Even then, you can use the "Capacity" property to force it to grow before hand, if you know how many elements you're adding (list.Capacity += numberOfAddedElements)



In general, I prefer to avoid array usage. Just use List<T>. It uses a dynamically-sized array internally, and is fast enough for most usage. If you're using multi-dimentional arrays, use List<List<List<T>>> if you have to. It's not that much worse in terms of memory, and is much simpler to add items to.

If you're in the 0.1% of usage that requires extreme speed, make sure it's your list accesses that are really the problem before you try to optimize it.


Actually arrays still have one advantage over Collections/Lists. Due to the way that Java implements Generics through type erasure, you cannot have two methods that take Collections as arguments yet only differ by the Collection's generic type.

Ex:

public void doSomething(Collection<String> strs) { ... }
public void doSomething(Collection<Integer> ints) { ... }

The two above methods will not compile because the javac compiler uses type erasure and thus cannot pass the type information to the JVM. The JVM will only see two methods that take a Collection as its argument.

In the above cases, the best work-around is to make the methods take arrays as their arguments and use the Collection/List's toArray() method when passing the arguments to them. If you still want to use Collection/List's inside the above methods, just use java.util.Arrays.asList() method to get your List back.

Ex:

public void doSomething(String[] strs) {
        List<String> strList = Arrays.asList(strs);
        ...
}

public void doSomething(Integer[] ints) {
        List<Integer> intList = Arrays.asList(ints);
        ...
}

public static void main(String[] args) {
        List<String> strs = new ArrayList<String>();
        List<Integer> ints = new ArrayList<Integer>();
        obj.doSomething(strs.toArray());
        obj.doSomething(ints.toArray());
}

How and when to abandon the use of arrays in C#?

Look at the generic List<T> as a replacement for arrays. They support most of the same things arrays do, including allocating an initial storage size if you want.


API java 5 and more: should I return an array or a Collection?

Prefer Collection (or List, or Set as appropriate) to an array. With generics you get the type-checking that was lacking pre-Java 5. Also, by exposing only the interface, you are free to change the implementation later (e.g. switch an ArrayList for a LinkedList).

Arrays and generics don't mix very well. So, if you want to take advantage of generics, you should usually avoid arrays.
I.e: You can't generically create an array. For example, if T is a generic type then "new T[0]" doesn't compile. You'd have to do something like "(T[]) new Object[0]", which generates an unchecked cast warning. For the same reason, you can't use generic types with varargs without warnings.

Using Collections.unmodifiableCollection (and similar methods), you get the read-only constraint (which you can't achieve with an array - you would have to return a clone of the array).

You can't enforce immutability of members, but then you can't do that with an array either.


I usually go for this, a public getter that returns System.Collections.ObjectModel.ReadOnlyCollection:

public ReadOnlyCollection<SomeClass> Collection
{
    get
    {
         return new ReadOnlyCollection<SomeClass>(myList);
    }
}

And public methods on the object to modify the collection.

Clear();
Add(SomeClass class);

If the class is supposed to be a repository for other people to mess with then I just expose the private variable as per method #1 as it saves writing your own API, but I tend to shy away from that in production code.


The Framework Design Guidelines suggest returning a copy of the Array. That way, consumers can't change items from the array.

// bad code
// could still do Path.InvalidPathChars[0] = 'A';
public sealed class Path {
   public static readonly char[] InvalidPathChars = 
      { '\"', '<', '>', '|' };
}

these are better:

public static ReadOnlyCollection<char> GetInvalidPathChars(){
   return Array.AsReadOnly(InvalidPathChars);
}

public static char[] GetInvalidPathChars(){
   return (char[])InvalidPathChars.Clone();
}

The examples are straight from the book.





architecture