Should I always return IEnumerable instead of IList?

后端 未结 14 1936
一生所求
一生所求 2020-11-27 11:47

When I\'m writing my DAL or other code that returns a set of items, should I always make my return statement:

public IEnumerable GetRecentItems         


        
相关标签:
14条回答
  • 2020-11-27 12:27

    Framework design guidelines recommend using the class Collection when you need to return a collection that is modifiable by the caller or ReadOnlyCollection for read only collections.

    The reason this is preferred to a simple IList is that IList does not inform the caller if its read only or not.

    If you return an IEnumerable<T> instead, certain operations may be a little trickier for the caller to perform. Also you no longer will give the caller the flexibility to modify the collection, something that you may or may not want.

    Keep in mind that LINQ contains a few tricks up its sleeve and will optimize certain calls based on the type they are performed on. So, for example, if you perform a Count and the underlying collection is a List it will NOT walk through all the elements.

    Personally, for an ORM I would probably stick with Collection<T> as my return value.

    0 讨论(0)
  • 2020-11-27 12:27

    I think you can use either, but each has a use. Basically List is IEnumerable but you have count functionality, add element, remove element

    IEnumerable is not efficient for counting elements

    If the collection is intended to be readonly, or the modification of the collection is controlled by the Parent then returning an IList just for Count is not a good idea.

    In Linq, there is a Count() extension method on IEnumerable<T> which inside the CLR will shortcut to .Count if the underlying type is of IList, so performance difference is negligible.

    Generally I feel (opinion) it is better practice to return IEnumerable where possible, if you need to do additions then add these methods to the parent class, otherwise the consumer is then managing the collection within Model which violates the principles, e.g. manufacturer.Models.Add(model) violates law of demeter. Of course these are just guidelines and not hard and fast rules, but until you have full grasps of applicability, following blindly is better than not following at all.

    public interface IManufacturer 
    {
         IEnumerable<Model> Models {get;}
         void AddModel(Model model);
    }
    

    (Note: If using nNHibernate you might need to map to private IList using different accessors.)

    0 讨论(0)
  • 2020-11-27 12:27

    I think the general rule is to use the more specific class to return, to avoid doing unneeded work and give your caller more options.

    That said, I think it's more important to consider the code in front of you which you are writing than the code the next guy will write (within reason.) This is because you can make assumptions about the code that already exists.

    Remember that moving UP to a collection from IEnumerable in an interface will work, moving down to IEnumerable from a collection will break existing code.

    If these opinions all seem conflicted, it's because the decision is subjective.

    0 讨论(0)
  • 2020-11-27 12:28

    It really depends on why you are using that specific interface.

    For example, IList<T> has several methods that aren't present in IEnumerable<T>:

    • IndexOf(T item)
    • Insert(int index, T item)
    • RemoveAt(int index)

    and Properties:

    • T this[int index] { get; set; }

    If you need these methods in any way, then by all means return IList<T>.

    Also, if the method that consumes your IEnumerable<T> result is expecting an IList<T>, it will save the CLR from considering any conversions required, thus optimizing the compiled code.

    0 讨论(0)
  • 2020-11-27 12:32

    I might be a bit off here, seeing that no one else suggested it so far, but why don't you return an (I)Collection<T>?

    From what I remember, Collection<T> was the preferred return type over List<T> because it abstracts away the implementation. They all implement IEnumerable, but that sounds to me a bit too low-level for the job.

    0 讨论(0)
  • 2020-11-27 12:33

    One thing to consider is that if you're using a deferred-execution LINQ statement to generate your IEnumerable<T>, calling .ToList() before you return from your method means that your items may be iterated twice - once to create the List, and once when the caller loops through, filters, or transforms your return value. When practical, I like to avoid converting the results of LINQ-to-Objects to a concrete List or Dictionary until I have to. If my caller needs a List, that's a single easy method call away - I don't need to make that decision for them, and that makes my code slightly more efficient in the cases where the caller is just doing a foreach.

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