tags:

views:

105

answers:

6

Hey guys,

I've got a class in my project that stores a List<> of elements. I'm trying to figure out whether I should allow the user to add to that List directly (e.g. Calling the native add/remove methods) or lock it down by declaring the List private and only allowing a handful of methods I choose to actually alter the List.

It's a framework, so I'm trying to design it as robustly as possible, but I also want to keep it as simple and error-free as possible.

What's the best practice in this situation?

Thanks, Tyler

+1  A: 

Keeping the list private gives you more control and may make it more robust (you can check values before accepting them into the list)

But keep it public is the simplest.

Shiraz Bhaiji
A: 

You could sub class the List and override the methods that modify the lists contents. In the override, you could either do additional processing to prevent the list from being modified, or you could fire an event so that you can be notified when the list changes. You could even just not call the base implementation in the overrides, and throw a NotSupportedException, if you wanted to disable the method altogether.

Dylan Vester
Then you could just keep your new subclassed list public and let the user use the list as they normally would.
Dylan Vester
While the NotSupportedException would work, that can't be very good design.
Lerxst
Depends on what you're actually disabling. You wanted to still allow them to add/remove entries from the list. What more does the list offer in terms of modification. Chances are, you won't even need to use a NotSupportedException.
Dylan Vester
I just mentioned the NotSupportedException as a means of disabling a method if you absolutly needed to. Take Linq to SQL for example, must collections are exposed as an IQueryable of something, this implements IEnumerable, as does List. It's perfectly acceptable to inherit from the built in types, and still keep all the additional extension methods you get for querying, but to add your own logic that may be required for your application.
Dylan Vester
+1  A: 

It really depends on what you are doing.

Personally, when I have a list in a custom class, and its providing, say, a list of business entities to a databound control, I would make it private and expose a couple of simple public methods to update it, and I could put extra code in there, like moving data around or whatever.

However, If the list is a result of some query, it may be better to expose the whole thing, and be able to use all your extension methods etc to work with it.

Its about whats best for the framework in context, in my opinion

Lerxst
+1  A: 

You should always keep your variables private. See Jon Skeets advice for details. Basically because you want to keep control on how you handle the data. The user does not need to know if it is a List or something else.

If you're using .NET 3.5 or above you can privately use a List<> and make a public property ReadonlyCollection. This is also thread-safe, but might require a bit of work on your side.

For that kind of questions, I can recommend FxCop. It analyzes your code and gives you hints on design, performance, etc.

+2  A: 

For a framework, I'd recommend to encapsulate the list completely and create methods to retrieve and add elements to it.

If the need arises to check the elements which are added, or events need to be fired for some actions, you'll be able to do that.

If you prefer to store those elements differently for whatever reason, you can.

On the other hand. if you allow to access the list directly, it will be difficult to go back and encapsulate it, or to change that and use something else. Code which uses this framework may depend exactly on that direct access to the list.

marapet
Why encapsulate when you can inherit and keep the power of the existing type?
Dylan Vester
I was thinking it would be better to encapsulate it - that way, only what is necessary is shown to the user.However, when utilizing the List in foreach situations, it just doesn't seem as intuitive as some of the other frameworks I've seen. For example, if I were to create a custom method to get a list enumerator, my foreach statement would be:foreach(Card card in Pile.GetCardEnumerator()){...}But other frameworks I've seen would probably use it like this:foreach(Card card in Pile.Cards){...}I guess the second option just seems better?
Tyler Murry
Mainly because it gives you the liberty of changing the way you handle those elements further down the road.
marapet
That's a valid point, however, sometimes it's nice to be able to use things that people have grown familar with using, such as the List object. That being said, there is something to be said about encapsulation that only exposes the methods and properties that you need, which by doing so, you make things easier to learn and use.
Dylan Vester
A: 

@Dylan Vester: As you should be favoring composition over inheritence, don't inherit the list. You may want to change it to a different data structure later, or perform some sort of validation/checking before adding to your list.

Mr Shoubs