I read a lot about why it is better to return an IEnumerable instead of an IList (or something like this). But now I stuck at some point.
Consider something like this: I have some functions that do multiple enumerations and therefore take an IReadOnlyCollection as a parameter, create a new List and return it as an IEnumerable.
IEnumerable<int> Foo1(IReadOnlyCollection<int> bar)
{
bar.Any();
bar.First();
return new List<int>() {1, 2, 3};
}
IEnumerable<int> Foo2(IReadOnlyCollection<int> bar)
{
bar.Any();
bar.First();
return new List<int>() {1, 2, 3};
}
IEnumerable Foo3 ...
Now if I want to call them one after another I have to do something like this
var tmp = Foo1(new List<int>() {1, 2, 3});
tmp = Foo2(tmp.ToList());
tmp = Foo3(tmp.ToList());
tmp = Foo4(tmp.ToList());
tmp = Foo5(tmp.ToList());
That means I have to create a 11 lists. The first one, one in every function and one for every function call. But in fact it would be enough to create 6 lists. Is there a better way or is this simply a possible drawback when returning IEnumerable?
In general, this is simply a tradeoff inherent in returning IEnumerable.
The advantage of returning IEnumerable is that you can change your Foo() implementation to return nearly any type of collection (or even a lazy sequence with yield return or LINQ) without changing the API. When creating an interface, it's important to balance this advantage against the fact that consumers of an IEnumerable API who want to enumerate it multiple times will always have to convert it to a collection.
Even more generally, returning a more specific type (e. g. List over IList) is most useful to consumers and most challenging in terms of maintaining the API. Some things to consider:
If you're just worried about the performance of creating new lists (which shouldn't be a real concern in nearly all cases), you can always create an extension as follows:
public static IReadOnlyCollection<T> AsReadOnlyCollection<T>(this IEnumerable<T> @this)
{
return @this as IReadOnlyCollection<T> ?? @this.ToArray();
}