tags:

views:

71

answers:

4

Seems like I can't do this:

private int[,] _table = new int[9, 9];
private ReadOnlyCollection<int[,]> _tableReadOnly = new ReadOnlyCollection<int[,]>(_table);

My idea is to have a property that let's the user read _table, but I don't want to let them change it, so I thought I could use ReadOnlyCollection for the matter.

A: 

I'm not entirely sure I understand the direction you were taking, but based on your description of what you're trying to accomplish, it seems to me that you can just do the following:

private int[,] _table = new int[9, 9];
public int[,] Table
{
    get
    {
     return _table;
    }
}
Steve Brouillard
That way anyone can do MyClass.Table[0,0] = 1111;
devoured elysium
Gotcha...makes more sense now.
Steve Brouillard
+6  A: 

The ReadOnlyCollection is a one dimensional collection. You could make a ReadOnlyCollection<ReadOnlyCollection<int>>, or make your own two dimensional wrapper class, something like:

public class ReadOnlyMatrix<T> {

   private T[,] _data;

   public ReadOnlyMatrix(T[,] data) {
      _data = data;
   }

   public T this[int x, int y] {
      get {
         return _data[x, y];
      }
   }

}
Guffa
+3  A: 

The problem is you're trying to wrap a 2D mutable structure with a 1D read only structure. You'll need several levels of nesting to accomplish this.

ReadOnlyCollection<ReadOnlyCollection<int>>

The downside to this approach though is that it will essentially force you to have the entire table in memory twice. ReadOnlyCollection<T> requires a List<T> as the sole constructor argument. So you will end up copying each one of your rows into a new List<int>.

Another way to accomplish this though is to use a property indexer to return the value directly without allowing for mutation.

public int this[int i, int j] {
  get { return _table[i,j]; }
}

This allows consumers to read the data without every having to mutate it.

JaredPar
+2  A: 

You could do something like:

public class ReadOnly2DArray<T>
{
    T[,] _array;
    public ReadOnly2DArray(T[,] arrayToWrap)
    {
        _array = arrayToWrap;
    }

    public T this[int x, int y]
    {
        get { return _array[x, y]; }
    }
}

possibly adding other methods of the Array class (Length property, GetLength method, ...) if you need them.

You'd then use it something like:

    int[,] a = new int[2, 2];
    ReadOnly2DArray<int> wrapper = new ReadOnly2DArray<int>(a);

    int value = wrapper[0, 0];  // Can read values
    //wrapper[0, 0] = value;      // Won't compile
Joe