.Net read only collections

Started by
6 comments, last by Mike.Popoloski 14 years, 11 months ago
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?
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Advertisement
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?
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...
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.


if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
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.
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]
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
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).
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.
Mike Popoloski | Journal | SlimDX

This topic is closed to new replies.

Advertisement