Why does IEnumerable.ToList() return List instead of IList?

前端 未结 10 1668
暖寄归人
暖寄归人 2020-12-29 02:23

The extension method ToList() returns a List. Following the same pattern, ToDictionary() returns a Dictionary<

相关标签:
10条回答
  • 2020-12-29 02:23

    Returning List<T> has the advantage that those methods of List<T> that are not part of IList<T> are easily used. There are a lot of things you can do with a List<T> that you cannot do with a IList<T>.

    In contrast, Lookup<TKey, TElement> has only one available method that ILookup<TKey, TElement> does not have (ApplyResultSelector), and you probably would not end up using that anyway.

    0 讨论(0)
  • 2020-12-29 02:23

    The short answer is that in general returning the most specific type available is recommended by the authoritative Framework Design Guidelines. (sorry I don't have a citation on hand, but I remember this clearly since it stuck out in contrast to the Java community guidelines which prefer the opposite).

    This makes sense to me. You can always do e.g. IList<int> list = x.ToList(), only the library author needs to be concerned with being able to support the concrete return type.

    ToLookup<T> is the unique one in the crowd. But perfectly within the guidelines: it is the most specific type available that the library authors are willing to support (as others have pointed out, the concrete Lookup<T> type appears to be more of an internal type not meant for public use).

    0 讨论(0)
  • 2020-12-29 02:28

    This is one of the common things that programmers have difficulty understanding around the use of interfaces and concrete types.

    Returning a concrete List<T> that implements IList<T> only gives the method consumer more information. Here is what the List object implements (via MSDN):

    [SerializableAttribute]
    public class List<T> : IList<T>, ICollection<T>, IList, ICollection, 
        IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
    

    Returning as a List<T> gives us the ability to call members on all of these interfaces in addition to List<T> itself. For example we could only use List.BinarySearch(T) on a List<T>, as it exists in List<T> but not in IList<T>.

    In general to maximize flexibility of our methods, we should take the most abstract types as parameters (ie. only the things we're going to use) and return the least abstract type possible (to allow a more functional return object).

    0 讨论(0)
  • 2020-12-29 02:29

    In my opinion returning a List<T> is justified by the fact that the method name says ToList. Otherwise it would have to be named ToIList. It is the very purpose of this method to convert an unspecific IEnumerable<T> to the specific type List<T>.

    If you had a method with an unspecific name like GetResults, then a return type like IList<T> or IEnumerable<T> would seem appropriate to me.


    If you look at the implementation of the Lookup<TKey, TElement> class with reflector, you'll see a lot of internal members, that are only accessible to LINQ itself. There is no public constructor and Lookup objects are immutable. Therefore there would be no advantage in exposing Lookup directly.

    Lookup<TKey, TElement> class seems to be kind of LINQ-internal and is not meant for public use.

    0 讨论(0)
  • 2020-12-29 02:31

    These kind of decisions may feel arbitrary but I guess that ToList() returns List<T> rather than an interface because List<T> both implements IList<T> but it adds other members not present in a regular IList<T>-typed object.

    For example, AddRange().

    See what IList<T> should implement (http://msdn.microsoft.com/en-us/library/5y536ey6.aspx):

    public interface IList<T> : ICollection<T>, 
        IEnumerable<T>, IEnumerable
    

    And List<T> (http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx):

    public class List<T> : IList<T>, ICollection<T>, 
        IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
        IEnumerable
    

    Maybe your own code doesn't require IReadOnlyList<T>, IReadOnlyCollection<T> or ICollection, but other components on .NET Framework and other products may rely on a more specialized list object and that's why .NET dev team decided to do not return an interface.

    Don't feel always return an interface is the best practice. It's if your code or third-party ones require such encapsulation.

    0 讨论(0)
  • 2020-12-29 02:31

    I believe that the decision to return a List<> instead of an IList<> is that one of the more common use cases for calling ToList is to force immediate evaluation of the entire list. By returning a List<> this is guaranteed. With an IList<> the implementation can still be lazy, which would defeat the "primary" purpose of the call.

    0 讨论(0)
提交回复
热议问题