Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why refactor argument of List<Term> to IEnumerable<Term>?

I have a method that looks like this:

    public void UpdateTermInfo(List<Term> termInfoList)
    {
        foreach (Term termInfo in termInfoList)
        {
            UpdateTermInfo(termInfo);
        }
        m_xdoc.Save(FileName.FullName);
    }

Resharper advises me to change the method signature to IEnumerable<Term> instead of List<Term>. What is the benefit of doing this?

like image 403
user829174 Avatar asked Dec 13 '11 12:12

user829174


2 Answers

The other answers point out that by choosing a "larger" type you permit a broader set of callers to call you. Which is a good enough reason in itself to make this change. However, there are other reasons. I would recommend that you make this change because when I see a method that takes a list or an array, the first thing I think is "what if that method tries to change an item in my list/array?"

You want the contents of a bucket, but you are requiring not just the bucket but also the ability to change its contents. Why would you require that if you're not going to use that ability? When you say "this method cannot take any old sequence; it has to take a mutable list that is indexed by integers" I think that you're making that requirement on the caller because you're going to take advantage of that power.

If "I'm planning on messing up your data structure" is not what you intend to communicate to the caller of the method then don't communicate that. A method that takes a sequence communicates "The most I'm going to do is read from this sequence in order".

like image 60
Eric Lippert Avatar answered Sep 29 '22 09:09

Eric Lippert


Simply put, accepting an enumerable allows your function to be compatible with a broader scope of input arguments, such as arrays and LINQ queries.

To expound on accepting LINQ queries, one could do:

UpdateTermInfo(myTermList.Where(x => somefilter));

Additionally, specifying an interface rather than a concrete class allows others to provide their own implementation of that interface. In this way, you are being "subscriptive" rather than "proscriptive." (Yes, I did just make up a word.)

In general (with many exceptions relating to what sort of abilities you want to reserve for potential later modifications), it is a best-practice to implement functions using arguments that are the most general that they can be. This gives maximum flexibility to the consumer of your function.

As a result, if you are dead-set on using a list for this function (perhaps because at some later date you expect you might want to use properties such as Count or the index operator), I would strongly urge you to consider using IList<Term> instead of List<Term> for the reasons mentioned above.

like image 43
David Pfeffer Avatar answered Sep 29 '22 11:09

David Pfeffer