Generic ReadOnlyCollection sealed

  • Thread starter Thread starter Ian Boisvert
  • Start date Start date
I

Ian Boisvert

I'm trying to create a custom read only collection. I found the generic
ReadOnlyCollection class and the documentation says "Implementers are
encouraged to extend this base class instead of creating their own."
OK, sounds good. The only problem is that it seems that most of the
methods of ReadOnlyCollection<T> are sealed, which makes extending the
class difficult. Have I missed something? Thanks.

Ian.
 
Ian said:
I'm trying to create a custom read only collection. I found the generic
ReadOnlyCollection class and the documentation says "Implementers are
encouraged to extend this base class instead of creating their own."
OK, sounds good. The only problem is that it seems that most of the
methods of ReadOnlyCollection<T> are sealed, which makes extending the
class difficult. Have I missed something? Thanks.

I guess you mean the methods are not virtual, right? In that case yes,
you are right. But there's nothing wrong with that, it's the same
pattern that's been used for all the other generic collection classes.
This shouldn't normally be much of a problem because the generic
collection class is typed already. You can derive your own type from it
and extend it with additional methods, if you want, or you can use it as
it is, because in contrast to the non-generic [ReadOnly]CollectionBase,
this is not an abstract class.

What exactly do you want to do in your derived class? Why is it a problem?



Oliver Sturm
 
Thanks, Oliver. What I want to be able to do is to provide a custom
enumerator so that I can iterate through only specific objects in a
"master collection" which the read-only collection wraps. To do this I
need to overload IEnumerable<T>::GetEnumerator (and
ICollection<T>::Count).

Ian.
 
Ian said:
Thanks, Oliver. What I want to be able to do is to provide a custom
enumerator so that I can iterate through only specific objects in a
"master collection" which the read-only collection wraps. To do this I
need to overload IEnumerable<T>::GetEnumerator (and
ICollection<T>::Count).

Why don't you just create an additional iterator instead of overriding
the standard one?

class MyCollection : ReadOnlyCollection<MyContent> {
...
public IEnumerable<MyContent> MyNewIterator() {
foreach (MyObject mo in this)
if (mo.SatisfiesMyCriteria())
yield return mo;
}
...
}

Actually, if I understand the scenario correctly that you are
describing, you could just as well implement this additional iterator
(or any number of them) directly in your "master collection". You can
even pass in parameters to the iterator to make it more flexible...


Oliver Sturm
 
Oliver, thanks for the suggestion. If I created a new method to return
a different enumerator, I would have a schitzophrenic collection which
is not a good solution IMHO.

For the record, I rolled my own read only collection class. I had some
trouble until I realized that you have to implement both of
IEnumerable::GetEnumerator and IEnumerable<>::GetEnumerator using
something like:
virtual IEnumerator^ GetEnumerator() = IEnumerable::GetEnumerator()
{...}
virtual IEnumerator<T>^ GetGenericEnumerator() =
IEnumerable<T>::GetEnumerator() {...}

So much for not having to reinvent the wheel...

Ian.
 
Ian said:
Oliver, thanks for the suggestion. If I created a new method to return
a different enumerator, I would have a schitzophrenic collection which
is not a good solution IMHO.

Well, that's the solution devised by the .NET team, and I like it. An
iterator is not about what a collection contains, but about enumerating
elements in a collection in a specific way. So I don't think you have a
schizophrenic collection, you just have a collection that knows how to
distinguish between different types of its elements and enumerate each
type accordingly.
For the record, I rolled my own read only collection class. I had some
trouble until I realized that you have to implement both of
IEnumerable::GetEnumerator and IEnumerable<>::GetEnumerator using
something like:
virtual IEnumerator^ GetEnumerator() = IEnumerable::GetEnumerator()
{...}
virtual IEnumerator<T>^ GetGenericEnumerator() =
IEnumerable<T>::GetEnumerator() {...}

So much for not having to reinvent the wheel...

Under many circumstances it's enough to have one of those, if I'm not
mistaken. It's also possible to implement the generic one "for real",
meaning with the algorithm that's needed to select the correct data you
need, and to just implement the non-generic method like this:

IEnumerator IEnumerable.GetEnumerator() {
foreach (T item in this)
yield return item;
}



Oliver Sturm
 
Back
Top