views:

129

answers:

3

I've recently started using F# for "real work" and rediscovered the beauty of immutable data structures such as the discriminated unions and records in F#. I've also found them to be quite straight forward to use from C#, especially as they don't require any direct dependencies on the F# runtime. However, when it comes to representing lists in these structures, I have not yet found an ideal solution.

My first attempt was to type the lists as seq<'a> (IEnumerable in the C# world) which provides a nice general collection interface without exporting any methods for mutating the collection the way ICollection<> and its friends does. However, since I have no control over the constructor of a discriminated union or record, it is possible for the creator of an instance of these types to provide an IEnumerable<> implementation that might change or throw when used (such as a LINQ expression). IEnumerable<> will therefor not give me any help from the compiler in proving that the value is immutable and therefor thread safe.

My current strategy is to use the F# list type which does guarantee an immutable collection, but adds a dependency on the F# runtime and looks a bit off when used from non F# projects. It does however allow for F# pattern matching which IEnumerable<> does not. It also doesn't give any choice in the actual representation of a list, and in some cases (such as large lists of primitive values) the F# list representation does not really fit.

What I really would like to see is an immutable array type in .NET, represented just as compactly as the normal array but with a compiler guarantee of not being mutated. I would welcome const as in C++ although it's probably not very likely to happen. In the meantime, is there any other option I've missed?

+7  A: 

If what you want is an immutable array implementation then you can just use something like the following

public sealed class ImmutableArray<T> : IEnumerable<T>{
  private readonly T[] m_array;
  public T this[int index] {
    get { return m_array[index]; }
  }
  public int Length {
    get { return m_array.Length; }
  }
  public ImmutableArray(IEnumerable<T> enumerable) {
    m_array = enumerable.ToArray();
  }
  // IEnumerable<T> implementation ommitted
}
JaredPar
That might indeed be the best way. The constructor would have to copy the array but at least you could freely pass around an instance of this type and know that it would not change its content.
Freed
+2  A: 

Wrap your normal array in a ReadOnlyCollection<T> instance:

var readOnlyData = new ReadOnlyCollection<TheType>(theRealCollection);

(Note, this does not copy the underlying collection, but holds a reference and and modifying members of IList<T> etc. are implemented to throw an exception.)

Richard
I would have to statically type the properties as ReadOnlyCollection<>, which is possible, but doesn't really offer any advantage over typing it as IEnumerable<>, as the creator could still provide a ReadOnlyCollection backed by a non-mutable collection. ReadOnlyCollection<> also implements a number of interfaces that an immutable collection should not support.
Freed
The problem with `ReadOnlyCollection<T>` though is it's not immutable, it's just readonly.
JaredPar
+1  A: 

I'd recommend looking at Eric Lippert's series on immutability, it's a very useful read. Part 4 about a immutable queue would be a good place to start.

Matt Warren
The problem is that my implementation of an immutable queue is not nearly as space-efficient as an array. An array of, say, bytes, takes up one byte per element. A queue of bytes takes up dozens of bytes per element.
Eric Lippert
Good point, I didn't think about that, thanks for the info.
Matt Warren
Although Erics blog is definitely interesting, what I was really looking for was an existing data structure to use for representing immutable lists, not how to implement an immutable list or any of the more challenging immutable data structures.
Freed