Skip to main content
gamedev.net
🔒 Locked

[.net] Read-only array from a class

Started by Sijmen Jan 14, 2005 at 3:18 AM 5 replies 1.1k views
Original Post
Sijmen
Sijmen
Hi there, Take this class I have, the Map class. It has an array of the type Team for the spawnpoints:

public class Map
{
	// ...

	Room[] teamstart;
	public Room[] TeamStart
	{
		get { return teamstart; }
	}
}	
Now there is this problem: a returned array is not read only. So the array itself is readonly, but the nodes are not. That means that it's possible to change the contents of the array. Since this is a map, I don't want it. What's the best way to fix this? I see three options: - Use an indexer on the Map class for the teamstarts. However, I already use the indexer for the rooms. - Create a GetSpawnpoint() method. This is inconsistent with the idea of properties and looks kind of weird. - Create a new class like ReadOnlyArray or something like that, that has an indexer. I don't know about this one either... What solution do you suggest? Any other solutions maybe?
fractoid
fractoid
I don't know C#, but I'd be surprised if they've done away with the 'const' keyword. Simply go:

public const Room[] [const] TeamStart { get { return teamstart; } }

The second const is in square brackets because whether it's needed depends on whether C# treats [] like a pointer or like an 'array object' a la Java.

[edit: It seems they may have done so after all, making this approach useless. Why, you fools?!? WHY?!??! *goes to research topic more* ]
Sijmen
Sijmen
In the meantime, I've wrote this helper class:

public struct TeamstartList{	TeamList teams;	public TeamstartList(TeamList teams)	{		this.teams = teams;		teamstarts = new Room[teams.Count];	}	Room[] teamstarts;	public Room this[Team team]	{		get { return teamstarts[teams.IndexOf(team)]; }		set { teamstarts[teams.IndexOf(team)] = value; }	}}
DrGUI
DrGUI
Something I intend to do sometime - create a readonly wrapper for the Array class, it probably needs to be generic but I haven't really looked into generics yet.

Just create lots of pass-through functions, but missing out all of the 'set' accessors.

There shouldn't be a performance penalty for this because the function calls should be inlined by the JIT.
turnpast
turnpast
If you are using dotnet 2.0 there is a method Array.AsReadOnly you might be interested in.

There is also an abstract class in System.Collections called ReadOnlyCollectionBase (available in dotnet 1.1) and a non abstract generic class ReadOnlyCollection (2.0 only)

If the type in the array is a value type and the Array is read only than you are safe from internal edits to the type, but not if it is a reference type.

Depending on how you use the array you might be better off just returning an Enumerator on the array than the actual array.
DaWanderer
DaWanderer
According to Microsoft's properties guidelines, you should just create a GetSpawnPoint method or something to that effect. Personally, I would create a SpawnPointCollection class like this:

public class SpawnPointCollection : System.Collections.ReadOnlyCollectionBase{   public void AddSpawnPoint(Room NewSpawnPoint)   {      InnerList.Add(NewSpawnPoint);   }   public Room this[int Index]   {      return( (Room)InnerList[Index] );   }}


If you really need it, you could add a RemoveSpawnPoint method. I'm assuming, though, that this will simply be read in from a map file, so it won't change during the course of the game.
kSquared
kSquared
Quote:
Original post by Sijmen
Now there is this problem: a returned array is not read only. So the array itself is readonly, but the nodes are not. That means that it's possible to change the contents of the array. Since this is a map, I don't want it.

That's right. When a value object is read-only, you can't change the value; when a reference object is read-only, you can't change the reference. So while you can't make the array reference point to a different object, but you can change the properties or elements of the array.

Instead of writing a whole new class/helper, why not try using an ArrayList and its associated IList.ReadOnly() interface member?

       // Creates a read-only copy of the ArrayList.       ArrayList noWriteAL = ArrayList.ReadOnly(myAL);
- k2 "Choose a job you love, and you'll never have to work a day in your life." — Confucius"Logic will get you from A to B. Imagination will get you everywhere." — Albert Einstein"Money is the most egalitarian force in society. It confers power on whoever holds it." — Roger Starr{General Programming Forum FAQ<

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.