In which interface should I open List <T> via?

In response to this question, runefs suggested that "unless you have a specific reason for using IList, you should consider IEnumerable." What do you use and why?

+4
source share
6 answers

IEnumberable<T> is read-only, you need to restore the collection to make changes to it. IList<T> , on the other hand, is read-write. Therefore, if you expect a large number of changes to the collection, print IList<T> , but if you can assume that you will not change it, go to IEnumerable<T> .

+12
source

Always use the most restrictive interface that provides the functions you need, as this gives you maximum flexibility to change the implementation later. So, if IEnumerable<T> enough, use this ... if you need list functions, use IList<T> .

And it is advisable to use strongly typed generic versions.

+7
source

The following principle is the one I read a while ago:

"Use the simplest and most complex"

(I'm sure this is really common, and I am quoting it incorrectly if someone knows that the source can leave a comment or change, please ...)

(Edited to add - well, here I am a couple of weeks later, and I just came across this quote in a completely different context, it looks like it started with the Principle of Reliability or the Postel Law -

Be conservative in what you do; Be liberal in what you accept from others.

The original definition is for network communication over the Internet, but I'm sure I saw that it was reprogrammed to define class contracts in OO.)

Basically, if you are defining a method for external consumption, then the parameters should be the most basic type that gives you the functionality you need. In the case of your example, this could mean accepting in IEnumerable instead of IList. This gives the client code more flexibility than what they can pass. On the other hand, if you expose the property for external consumption, then do it with the most complex type (IList or ICollection instead of IEnumerable), since this gives the client the greatest flexibility in how they use the object.


I find the conversation between myself and Dr. Jokepu in the comments fascinating, but I also appreciate that this should not be a discussion forum, so I will edit my answer to further outline the reasons underlying my choice, the trend and suppose that you expand it as an IList (well, actually, a List, as you will see). Let's say this is the class we're talking about:

 public class Example { private List<int> _internal = new List<int>(); public /*To be decided*/ External { get { return _internal; } } } 

So, first of all, let's say that we expose External as IEnumerable. The reasons that I saw for this in other answers and comments currently are:

  • IEnumerable Read Only
  • IEnumerable is the defacto standard.
  • It reduces communication, so you can change the implementation
  • You do not disclose implementation details

While IEnumerable only provides readonly functionality, which does not make it read-only. The real type that you return is easily detected by reflection or just pauses the debugger and looks, so it is trivial to return it to List <>, the same applies to the FileStream example in the comments below. If you are trying to protect the participant, then pretend that this is something else, this is not a way to do it.

I do not believe this is a defacto standard. I can’t find any code in the .NET 3.5 library where Microsoft had the opportunity to return a specific collection and instead returned the interface. IEnumerable is more common in 3.5 thanks to LINQ, but this is because they cannot expose a more derived type, and not because they do not want to.

Now, by decreasing the connection, I agree - with a dot - basically this argument seems to be that you are telling the client that while the returned object is a list that I want you to consider is IEnumerable just in case case you decide to change the internal code later. Ignoring the problems with this and the fact that the real type is exposed anyway, it still leaves the question "why dwell on IEnumerable?". if you return it as an object type, then you will have complete freedom to change the implementation to anything! This means that you had to make a decision about how many functions are required for the client code, either you write client code or the decision is based on arbitrary indicators.

Finally, as discussed earlier, you can assume that implementation details are always displayed in .NET, especially if you are publicly exposing the object.

So, after this long diatribe, one question remains: why expose it as a List <>? Why not? You got nothing by exposing it as IEnumerable, so why artificially limit the ability of client code to work with an object? Imagine if Microsoft decided that the Controls collection of the Winforms control should be displayed as IEnumerable instead of the ControlCollection - you can no longer pass it to methods that require IList, work with arbitrary index elements or see if it contains a specific control if you haven’t done it. Microsoft really won’t win, and you’re just not comfortable.

+4
source

When I only need to list the children, I use IEnumerable. If I need a graph, I use ICollection. However, I try to avoid this as it provides implementation details.

+3
source

IList<T> really a very wise interface. I prefer to expose Collection<T> -deleted types. This is largely consistent with what Jeffrey Richter offers (there is no book nearby, so cannot specify the page / section number): methods should take the most common types as parameters and return the most derived types, such as return values.

+2
source

If a read-only collection is opened through a property, then the usual way to do this is to expose it as ReadOnlyCollection (or a derived class) that wraps everything you have. It provides the client with all the capabilities of IList, and yet it shows very clearly that it is read-only.

+1
source

All Articles