Why we don’t recommend using List<T> in public APIs


We don’t recommend using List<T> in public APIs for two reasons.



  • List<T> is not designed to be extended. i.e. you cannot override any members. This for example means that an object returning List<T> from a property won’t be able to get notified when the collection is modified. Collection<T> lets you overrides SetItem protected member to get “notified” when a new items is added or an existing item is changed.

  • List<T> has lots of members that are not relevant in many scenarios. We say that List<T> is too “busy” for public object models. Imagine ListView.Items property returning List<T> with all its richness. Now, look at the actual ListView.Items return type; it’s way simpler and similar to Collection<T> or ReadOnlyCollection<T>.

 

Comments (30)

  1. Rob P says:

    List<T> has so much useful stuff on it though 🙂 Stuff, I might add, that is probably implemented using only members from IList (Find, FindAll, etc).

    I guess we can wait for c# 3 and just extend IList<T> to have all the methods of List<T> we want.

  2. Is there a replacement generic type that you recommend using instead?

  3. We recommend using Collection<T>, ReadOnlyCollection<T>, or KeyedCollection<TKey,TItem> for outputs and properties and interfaces IEnumerable<T>, ICollection<T>, IList<T> for inputs.

    If you need the List<T> useful APIs on your public API, just inherit from Collection<T> and add these APIs.

  4. Mark Bower says:

    Interesting. So you could say Collection<T> is the Generic equivalent of CollectionBase from v1.1?

  5. Yes, Collection<T> is just a better CollectionBase. See http://blogs.msdn.com/kcwalina/archive/2005/09/23/Collections.aspx for more details.

  6. Michael Primeaux says:

    What is the recommended pattern for implementing a synchronized class that inherits from Collection<T>?  For example, I want to implement a SyncRoot property of type ReaderWriterLock. I do see where I can override (protected) the methods InsertItem, RemoveItem, ClearItems, and SetItem. However, I do not see an override for GetItem.

  7. DoNotExposeGenericLists fires when I publicly expose a List&amp;lt;T&amp;gt; via a field, method, property, or…

  8. Roger says:

    <<We recommend using Collection<T>, ReadOnlyCollection<T>, or KeyedCollection<TKey,TItem> for outputs and properties and interfaces IEnumerable<T>, ICollection<T>, IList<T> for inputs. >>

    Lets say I have my own collection of Persons deriving from collection<t> where I’ve added some new functionality… Do you mean that I should return a collection<t> instead of my derived collection type in a method returning Persons? Why? Harder for the clients to get hold of my collection specific API. Or do I misunderstand you?

  9. Perry Rapp says:

    Let me ask again a great question above (Michael’s), which was apparently never answered:

    What is the recommended pattern for implementing a synchronized class that inherits from Collection<T>?

  10. Forse ha ragione David: la mia risposta al post di Giulio (per quanto sintetica e quindi non esaustiva) non

  11. Michael and Perry, I will try to write some detailed guidelines on synchronization and post them to this blog. Unfortunatelly I am swampped right now and this is a relativelly large project. But quickly, in most scenarios, we recommend you wrap all collections and other components that need to be synchronized. In some other scenarios where the only resource that needs to be synchronized is the collection, I would simply inherit and add a sync root, optionally override the for protected members that modify Collection<T> and synchronize there.

  12. DoNotExposeGenericLists fires when I publicly expose List&lt;T&gt; via a field, method, property, or

  13. Andreas says:

    What would you recommend in this scenario:

    We have a class with an abstract method that is intended to be subclassed by the user of our framework. The method to override should produce a list of items that are determined in an application specific way.

    Is it ok for this method to look like this:

       protected abstract IEnumerable<Item> GetItems(…);

    > We recommend using … IEnumerable<T>, … for inputs.

    I would argue that the output from this overridden method is the input to our API, and as such IEnumerable has the least requirements for the implementation.

    How about users that use other languages than C#and VB? As far as I know, generics are CLS compliant. Can everybody override such a method?

  14. An Phu says:

    What are your recommendations in a webservice context?

  15. Hi Krzysztof! Sorry for putting it here, but don’t you think that there is a small bug in http://blogs.msdn.com/fxcop/archive/2006/04/27/585476.aspx example they put to explain your post? (Comments not allowed there). In class Person they have

    private AddressCollection _Addresses = new AddressCollection();

    But class AddressCollection does not have such parameterless constructor. The only one available takes Person owner parameter:

    public AddressCollection(Person owner)

  16. Vladimir,

    thanks for pointing it out. I will email the fxcop team about it.

  17. Phani says:

    What is the general recommendation for using List in WCF Operations?

  18. ae says:

    what is recommended in frk 3.5 ?? thanks.

  19. Jaz says:

    What about Linq?  

    The .ToList() isn’t a .ToCollection() in Linq-to-.  

    Is there an advantage that Microsoft sees that FxCop is missing? or am I missing something?  I want to use Linq on a List<T> even if it doesn’t come from Linq-to-Sql.