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