Delen via


Which collection interface do I use?

ReSharper has a warning that I thought came from FxCop that is so important I wish it was an FxCop warning. It warns you if you try to enumerate an IEnumerable twice. This is important when you take a collection as an argument and you do not know how that collection is created. For example if the collection is created by a method that just yield returns a few times, the second enumeration of that collection will never return any elements. Another more common and possible worse case is when the collection is created from a database query or similar so that a second enumeration will talk to the database a second time. Something that can be devastating for performance in your application.

So when you need to take a collection as an argument in your interface the guideline is actually very easy. Since it is an argument you know how you will use it. If you just need to enumerate once then you should take an IEnumerable as your argument since it gives your callers maximum flexibility. If you need to enumerate twice then ICollection should be your choice. That is for all your generic needs. Occasionally you actually want a the specific collection classes (Dictionary, HashSet, Queue etc) in which case you obviously should use those, but if you can use IEnumerable or ICollection you should in my opinion.

So what do you do when you return a collection? Here tend to prefer ICollection over anything else. Returning an IEnumerable when the collection already is a List or similar typically just causes the callers to convert the IEnumerable to a list so that they safely can enumerate it multiple times. And you need to be extra careful when creating public APIs that will be spread and used a lot since in that case you don't want to change your API (naturally you could add a new method so that you have one that returns ICollection by wrapping the IEnumerable one or vice versa).