Use Collection<T> Instead of List<T> for Public API

I love FxCop. I really do. But I find it very disheartening that most developers don't use it. Heck, there's plenty that have never even heard of it. It does an amazing job of performing static code analysis on .NET assemblies, which helps keep your overall design in check.

Of its many rules, FxCop has a rule named DoNotExposeGenericLists, which is described as:

Do not expose List<T> in object models. Use Collection<T>, ReadOnlyCollection<T> or KeyedCollection<K,V> instead. List<T> is meant to be used from implementation, not in object model API. List<T> is optimized for performance at the cost of long term versioning. For example, if you return List<T> to the client code, you will not ever be able to receive notifications when client code modifies the collection.

David Kean from the MS Code Analysis team does a good job of expanding on why that rule is in place. His post provides a good example that hopefully drives the point home. Take a second to read it.

But my point is that I find it very frustrating to run FxCop on an assembly only to find that it raises tons of issues specific to this rule. My take on the reasons for this are either:

  1. The developer doesn't know FxCop exists OR
  2. The developer knows of FxCop but doesn't use it OR
  3. The developer uses it but ignores the rule OR
  4. The developer uses it but turns that rule off OR
  5. The developer uses it but never bothers to check why the issue is raised

I can't do much about #1. Someone doesn't know what they don't know. All I can try to do is expose developers to the tool and hope they see its benefit. #2 I attribute to laziness. If a developer knows about FxCop and understands its benefits, the only reason I can think of for *not running it* is laziness. My guess is that it's because more than likely FxCop is going to expose issues that a developer doesn't want to take the time to address or just plain doesn't want to know about in the first place. And that's just sad.

For #3, #4, and #5, which are basically the same thing, I believe it's a bit of laziness mixed with personal preference for how code is written. For example, look at these two method signatures:

public List<Customer> GetCustomersByState(string stateAbbreviation)
public Collection<Customer> GetCustomersByState(string stateAbbreviation)

Now look at these two snippets:

List<Customer> customers = new List<Customer>();
Collection<Customer> customers = new Collection<Customer>();

The difference is that using List<Customer> is *shorter* than using Collection<Customer>, thus giving the perception that code with List<T> is more concise. Also, with List<T> there are less characters to type, which is silly considering if you start typing Collection<T> Intellisense kicks in about the time you get to "Co". So I don't buy the "I have to type less" argument.

I also think there might be one other reason developers default to use List<T> instead of Collection<T>: it lives in the System.Collections.Generic namespace, which is where most developers look when dealing with generics. However, Collection<T> lives in the System.Collections.ObjectModel namespace, which frankly many developers don't know exist.

There are times when using List<T> makes sense, such as when you want an easy way to invoke Sort or Find. But those are going to be used as part of logic *inside* a method, which does satisfy the rule:

List<T> is meant to be used from implementation, not in object model API.

So let's try and get better at this going forward by not only using FxCop, but taking the time to actually understand what it's trying to tell us. Our code will be better off for it.

Print | posted on Wednesday, January 09, 2008 12:47 AM

Feedback

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Karthik at 1/9/2008 9:24 AM
Great info! I've been guilty of doing this quite often when I write "throw-away" code that won't get exposed out to any users. There are definitely times when I don't bother running FxCop on that type of code.

But on a past project that relied on using in-memory storage via collections, we took things a step further by not exposing list properties as a List<T> but rather as a custom class (i.e. PersonCollection). Internally this class would store either a List<T>. The reason for doing this was to make the collection more thread safe.

Now I realize that had we used a Collection<T> class, we could have done the locking on the Collection methods just as easily.

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Jay R. Wren at 1/9/2008 9:39 AM
I prefer to expose IList<T>. This allows me to program to interfaces and hides the implementation of the list. Further, the runtime knows to treat an array of T as an IList<T> so I can use List<> or T[] or LinkedList<T> or something from C5 or Iesi or PowerCollections.

Programming to interfaces is really the best thing to do here.

The caveat is that XmlSerializer doesn't work with interfaces. IMO XmlSerializer is obsolete. Use the DataSerializers in .net 3.0 (they look like they are part of WCF, but they are themselves, excellent).

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Dave at 1/9/2008 9:57 AM
Jay - You're certainly right. My point was specific to List<T> and Collection<T>, but IList<T> probably makes the most sense in most cases. Good call.

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Steve Campbell at 1/9/2008 12:41 PM
I guess I fall into camp #2 (know about it but don't use it). My reason is nothing to do with laziness. It is simply that obscure rules with little or no benefit just annoy me. I prefer to get on with the job of writing quality software that works.

Maybe if I move to an environment where it is already implemented, I might become a fan. But I don't think so.

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Dave at 1/9/2008 12:50 PM
Steve - I hear you, but if you ran FxCop the rule would no longer be obscure now would it? FxCop's job *is* to annoy you so that you are aware of potential code and design issues, thus allowing you to write even better quality code that works. And why do you have to go someplace that already uses it before you'll use it yourself? To me, that sounds like you'd only use it because you were forced to use it, but only grudgingly so. I'd rather be more proactive than that.

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Steve Campbell at 1/10/2008 11:21 AM
I have tried FxCop of course. But we have lots of existing code, and lots of broken rules. I found myself having to evaluate each rule to see whether the cost of conforming would outweigh the value of the rule itself.

In doing that, I found that the percentage of valuable rules was too low, compared to the cost of implementing them. The cost is the training of each developer to understand the rule, the failed builds where the rule is broken, updating existing code to follow the rule (a big one time cost), etc.

In short - I do not use FxCop on my existing project, because the return on investment is not good enough.

In a project that already uses FxCop, I assume that most of the investment would already have been made, and the cost-benefit equation would be different.

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Dave at 1/10/2008 11:34 AM
Steve - Now that you put it that way, yes, I agree. Trying to backdoor FxCop into an existing codebase is tough, no doubt about it. You'll definitely be more successful with FxCop if it's used throughout the project lifecycle.

# re: Use Collection<T> Instead of List<T> for Public API

Gravatar left by Steven Harman at 1/16/2008 10:28 AM
Dave & Jay, You are my heros!

My team had this same conversation earlier this week and I never thought about just using IList<T>... and I do loves me some Interfaces!
Comments have been closed on this topic.