Sébastien Lorion <[EMAIL PROTECTED]> wrote:

> I will give a longer reply later, but two quick questions:
> 
> 1) How do you make your tree read-only ? Ex.: A method builds a tree and
> returns it as read-only. There must be no way other than using reflection to
> circumvent that.

I'm not sure that's very important. I make a distinction between two
kinds of collection classes: those designed to be exposed to the
"outside" world and thus need to be robust in terms of maintaining
semantic integrity, and those that are designed to be efficient and have
lots of algorithms etc. directly available on them, and are used in the
implementation of other classes.

For example, the .NET BCL has both Collection<T> and List<T>, and on
their face they seem quite similar. Why have both? Well, Collection<T>
has a smaller public API, and has virtual methods that help maintain
semantic integrity. On the other hand, List<T> has methods for sorting,
no new virtual methods, and no help for maintaining semantic integrity.
If you want to return a read-only list when you've started with a
List<T>, you might consider creating a ReadOnlyCollection<T> and passing
the List<T> to the constructor, thereby creating a read-only view by
proxy.

So, if a read-only view is badly needed, then a read-only proxy would be
one way to do it. It might be better to separate the payload of the tree
explicitly from the (logical) tree node in that case, though, otherwise
accessing the members of the logical tree node would require extra work
and probably wouldn't be statically type safe. Since the jobs I put my
trees to are very tree-oriented, I don't usually go down this route, and
live with mutable classes.

BTW, because C# doesn't support tail recursion, the ideal technique I'd
use - immutable classes - sometimes isn't possible. An alternative
technique would be some kind of TreeBuilder<T> that uses a combination
of delaying construction and private knowledge of the link fields to
avoid excessive recursion. That would need some kind of loose binding
for the constructors though, in order to keep the number of possible
tree node types unbounded.

> 2) How do you handle enumerator versionning ?

I don't sweat it. Enumerator versioning is (ISTM) mostly a way of
guarding against concurrency problems and should only be visible in
buggy programs, while I'm more or less philosophically opposed to
sharing mutable data structures across threads outside of a handful of
well-understood idioms, such as queues, dictionaries, etc. I personally
wouldn't sacrifice much performance to maintain a versioning semantic.

I believe that when you think about it, trees are a lot less suited to
general collection idioms than are array-based lists, because clients of
tree structures typically choose a tree for its intrinsic properties and
possibly while maintaining a bunch of other invariants, rather than
simply as a bucket of values. So, one sees things like SortedList<,>
which uses a tree internally, but doesn't expose it to the outside
world, since not every person who needs a tree needs a sorted tree, much
less one as specific as the one SortedList<,> uses.

FWIW, I think you'd be better off developing a tree / graph library as
you're finding uses for it, then re-adapting it for open source
purposes, rather than doing it in the other way around. Once upon a time
I fell into the trap of doing a library that way, and ended up
over-engineering it, and regretted keeping it smaller.

-- Barry

-- 
http://barrkel.blogspot.com/

===================================
This list is hosted by DevelopMentor®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to