Carmax
Carmax

Reputation: 2917

Avoid Generic Lists in Base Class - Should I Follow the Same Rule for Dictionary?

I was advised to change a List<string> property to a Collection<string>, in a base class, because it is more appropriate for inheritance.

This 'rule' was referred to: https://msdn.microsoft.com/en-us/library/ms182142.aspx

System.Collections.Generic.List is a generic collection that is designed for performance and not inheritance. System.Collections.Generic.List does not contain virtual members that make it easier to change the behavior of an inherited class. The following generic collections are designed for inheritance and should be exposed instead of System.Collections.Generic.List.

System.Collections.ObjectModel.Collection<T>

System.Collections.ObjectModel.ReadOnlyCollection<T>

System.Collections.ObjectModel.KeyedCollection<TKey, TItem>

Does a similar rule apply to Dictionary<string, string>?

I ask because it is also in the System.Collections.Generic namespace. Or maybe I have misunderstood and the rule only applies to Lists.

BTW, the Dictionary purpose is to hold errors (in a similar format to ModelState). I am not currently sure at exactly what stage I will be adding errors to it.


If I should be avoiding Dictionary<string, string> in the base class, what should I be using in it's place?

I have come across KeyedCollection but not sure if that is a good replacement.

Upvotes: 4

Views: 175

Answers (2)

Manuel Zelenka
Manuel Zelenka

Reputation: 1634

So basically what you were told could potentially be wrong for the use case you are going for.

The statement in the msdn article means by inheritance if you want to create your own implementation of a collection by deriving from it like so:

public class MyCollection : Collection<MyType>

The advantage of using Collection<T> in this scenario is that you can alter the behavior significantly as it exposes the following methods which can be overriden: ClearItems, InsertItem, RemoveItem and SetItem. When you derive from List<T> you can't override any methods at all (except for the standard ToString, Equals and GetHashCode).

But as you stated in your comment you use the List/Dictionary/Collection as a property. Therefore it rather depends on your own use case.

If you want deriving classes to just use the collection from the base class you can let it be whatever you think is best suited for your needs. But if you think that the deriving class will know better which collection to use then you should pick an interface from the System.Collections.Generic namespace.

I won't tell you which types or interfaces you should use when as it heavily depends on which functionality you need.

And by the way: the KeyedCollection can only be used to create your own key value collection (it is abstract). Therefore having a KeyedCollection as a property would mean that you'd also need an implementaion of a KeyedCollection.

Upvotes: 2

Alexei Levenkov
Alexei Levenkov

Reputation: 100547

Dictionary<TKey, TValue> does not have any base class you can use instead of it. It may be better to use interface (IDictionary<TKey, TValue> or maybe IReadOnlyDictionary<TKey, TValue> -both implemented by Dictionary), but it depends on your needs.

Note that it is very hard to express whether property returns internal storage or clone (and hence what happens when caller changes object) - you may want to consider IEnumerable<T> or methods that hide dictionary as implementation details.

Upvotes: 4

Related Questions