Readonly array elements

D

Dom

I have a class called GridCell, and I have an array of objects each declared as GridCell. The array is ReadOonly, done like this:

private GridCell[] m_Cells;
public GridCell[] Cells {get {return m_Cells;} private set {m_Cells = value;}}

Of course, the caller can't do this:
Cells = new GridCell[9];

But I was surprised to find he can do this:
Cells[0] = new GridCell(...)

How do I prevent the latter? BTW, I'm using arrays and not CollectionBase, because I think it is easier, simpler, and probably faster.

Dom
 
B

bradbury9

El martes, 20 de agosto de 2013 17:43:27 UTC+2, Dom escribió:
I have a class called GridCell, and I have an array of objects each declared as GridCell. The array is ReadOonly, done like this:



private GridCell[] m_Cells;

public GridCell[] Cells {get {return m_Cells;} private set {m_Cells = value;}}



Of course, the caller can't do this:

Cells = new GridCell[9];



But I was surprised to find he can do this:

Cells[0] = new GridCell(...)



How do I prevent the latter? BTW, I'm using arrays and not CollectionBase, because I think it is easier, simpler, and probably faster.



Dom

instead of

return m_Cells;

you could return a readonly copy. check AsReadOnly method bellow http://msdn.microsoft.com/en-us/library/53kysx7b.aspx
 
B

bradbury9

El martes, 20 de agosto de 2013 19:30:09 UTC+2, bradbury9 escribió:
El martes, 20 de agosto de 2013 17:43:27 UTC+2, Dom escribió:
I have a class called GridCell, and I have an array of objects each declared as GridCell. The array is ReadOonly, done like this:
private GridCell[] m_Cells;
public GridCell[] Cells {get {return m_Cells;} private set {m_Cells =value;}}
Of course, the caller can't do this:
Cells = new GridCell[9];
But I was surprised to find he can do this:
Cells[0] = new GridCell(...)
How do I prevent the latter? BTW, I'm using arrays and not CollectionBase, because I think it is easier, simpler, and probably faster.
Dom



instead of



return m_Cells;



you could return a readonly copy. check AsReadOnly method bellow http://msdn.microsoft.com/en-us/library/53kysx7b.aspx

I would use m_Cells.Clone() method as long as AsReadOnly return a collection not an array.
 
J

Jeff Johnson

I have a class called GridCell, and I have an array of objects each
declared as GridCell.
The array is ReadOonly, done like this:

No, the PROPERTY is (functionally) read-only, NOT the array.
private GridCell[] m_Cells;
public GridCell[] Cells {get {return m_Cells;} private set {m_Cells =
value;}}

Of course, the caller can't do this:
Cells = new GridCell[9];

But I was surprised to find he can do this:
Cells[0] = new GridCell(...)

How do I prevent the latter? BTW, I'm using arrays and not
CollectionBase, because I think it
is easier, simpler, and probably faster.

....and, due to the way arrays work, completely impossible for you to do what
you want to do.

The Get accessor returns THE ARRAY, nothing more, nothing less. The caller
now has complete access to the array and its members, which is why Cells[0]
= new GridCell(...) works just fine. You can't stop this as long as you are
returning a vanilla .NET array.
 
D

Dom

So i Seem to have two alternatives:

First ...
private GridCell m_Cells;
public IList<GridCell> Cells {get {return Array.AsReadOnly<GridCell>(m_Cells);} }

In this case, the original class call add members with m_Cells = new GridCell(...)

Second ...
private GridCell m_Cells;
public GridCellCollection Cells {get; set}

GridCellCollection is derived from CollectionBase, and I do things within the class to make sure the caller can not change or add anything.

Any idea which is the best approach?

Dom
 
A

Arne Vajhøj

I have a class called GridCell, and I have an array of objects each declared as GridCell. The array is ReadOonly, done like this:

private GridCell[] m_Cells;
public GridCell[] Cells {get {return m_Cells;} private set {m_Cells = value;}}

Of course, the caller can't do this:
Cells = new GridCell[9];

But I was surprised to find he can do this:
Cells[0] = new GridCell(...)
How do I prevent the latter? BTW, I'm using arrays and not CollectionBase, because I think it is easier, simpler, and probably faster.

Arrays are a low level construct where you can not restrict access to
element.

Your private setter prevents setting m_Cells to point to a new array -
it does nor prevent setting elements of the array to new values.

Drop arrays and switch to collections, they give you the desire
control over access to elements.

Arne
 
A

Arne Vajhøj

So i Seem to have two alternatives:

First ...
private GridCell m_Cells;
public IList<GridCell> Cells {get {return Array.AsReadOnly<GridCell>(m_Cells);} }

In this case, the original class call add members with m_Cells = new GridCell(...)

Second ...
private GridCell m_Cells;
public GridCellCollection Cells {get; set}

GridCellCollection is derived from CollectionBase, and I do things within the class to make sure the caller can not change or add anything.

Any idea which is the best approach?


I would pick the third option:

private IList<GridCell> m_Cells;
public IList<GridCell> Cells { get { return m_cells.AsReadOnly(); } }

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top