Sign in to follow this  
ChaosEngine

.Net read only collections

Recommended Posts

I find the .Net framework collections hierarchy kinda frustrating at times. The class tree looks like this (obviously vastly simplified)
                     IEnumerable<> // allows iteration only
                          |
                     ICollection<> // adds Count (and misc other stuff)
                          |
        ---------------------------------------
        |                                     |
     IList<> // adds random access,      IDictionary<> // adds keyed-access,
        |  // but also add/remove             |      // but also add/remove
        |                                     |
      List<> // implements IList         Dictionary<> // implements IDictionary  
Now this is fine, but alot of times I find I'd like to expose an immutable collection. IEnumerable/ICollection give us this, but we lose the ability to randomly access elements (by index or key). I can't help feel that there should've been an IRandomAccess or IKeyedAccess between ICollection and IList/IDictionary. Obviously I could just add a comment that says "please don't add or remove items in this collection", but it would be nice if I could express that in code. Does anyone else feel like this? Am I missing a really obvious solution?

Share this post


Link to post
Share on other sites
I can't say I've had that problem, although maybe that's because I haven't delved too much into it.

What exactly are you wanting to do?

Share this post


Link to post
Share on other sites
Quote:
Original post by Moe
I can't say I've had that problem, although maybe that's because I haven't delved too much into it.

What exactly are you wanting to do?


Typically, I've built a collection from some external source (a database, web service, whatever). Clients can enumerate over the list, index it, but it makes no sense for them to be able to add/remove elements from it.

Quote:
Original post by feal87
List.AsReadOnly() anyone?

http://msdn.microsoft.com/en-us/library/e78dcd75.aspx

Expose your object with this method and you can have a read-only List...


That's a run-time mechanism. ReadOnlyCollection still has an Add operation, it just throws an exception. Seems like an after-thought if you ask me.


Share this post


Link to post
Share on other sites
I've been frustrated by this somewhat as well, in that it feels unclean to have exposed methods that modify a collection that really shouldn't be modified, but over time I've accepted ReadOnlyCollection as adequate.

For me, it helps to remember that in .NET there's really no concept of a truly immutable object. The refleciton API can crack open almost anything and gives you quick and easy access to private members. If somebody really, REALLY wants to do it, they will. As a result, I generally consider a good-faith effort to warn the user not to do something as enough of a precaution. Having no public add method would be ideal, but an add method that throws an exception is sufficient warning that it shouldn't be done.

In short, I think preventing accidental misuse is really the best that can be hoped for. Beyond that, let them do what they will.

Share this post


Link to post
Share on other sites
Quote:
Original post by JPatrick
I've been frustrated by this somewhat as well, in that it feels unclean to have exposed methods that modify a collection that really shouldn't be modified, but over time I've accepted ReadOnlyCollection as adequate.

For me, it helps to remember that in .NET there's really no concept of a truly immutable object. The refleciton API can crack open almost anything and gives you quick and easy access to private members. If somebody really, REALLY wants to do it, they will. As a result, I generally consider a good-faith effort to warn the user not to do something as enough of a precaution. Having no public add method would be ideal, but an add method that throws an exception is sufficient warning that it shouldn't be done.

In short, I think preventing accidental misuse is really the best that can be hoped for. Beyond that, let them do what they will.


Completely agree. What I'm after here is not security, but prevention of coding error. I'm a firm believer in making it difficult to do the wrong thing in code. After all, I've really no control I've who will have to use my code. Hell, it could even be me and I don't trust me not to screw it up! [grin]

Share this post


Link to post
Share on other sites
Alas, this stems from the fundamental problem that a good percentage of the original (.NET 1) base interfaces and classes were not as well-thought-out as they could (or that intentional design decisions were made that have now turned out to be suboptimal, one of the two).

You can build your own collection APIs that have stronger interface contracts. This is more viable these days with extension methods that let you hoist some compatibility with your new APIs into other objects... but it still won't be perfect since many APIs expect the standard collections. You can also use existing third-party collection APIs, such as the C5 Collections Library, which I used for a while and found quite good overall (although I eventually abandoned it because of a event-related bug they chose not to fix).

Share this post


Link to post
Share on other sites
Well, assuming you're using .NET 3.5 you can always make use of the LINQ method ElementAt(). Internally, it checks if the IEnumerable<T> it is wrapping implements IList<T>, and if it does it will index using the indexer. If it does not, if will run through the collection until it gets to the appropriate index.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this