Question: Have I got this example backwards?
Is the reason to return Interface so that:
Try1:
public class Thing
{
public string name { get; set; }
public int age { get; set; }
public IList<Thing> giveMeAllThings()
{
IList<Thing> listOfThings = new List<Thing>();
Thing thing1 = new Thing { name = "phone", age = 3 };
Thing thing2 = new Thing { name = "waterbottle", age = 2 };
Thing thing3 = new Thing { name = "pinecone", age = 17 };
listOfThings.Add(thing1);
listOfThings.Add(thing2);
listOfThings.Add(thing3);
return listOfThings;
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void UnitTestThings()
{
Thing thing = new Thing();
IEnumerable<Thing> listOfThings = thing.giveMeAllThings();
Assert.AreEqual(3, listOfThings.Count()); // linq count
Assert.IsTrue(listOfThings.Any(t => t.name == "phone" && t.age == 3));
Assert.IsTrue(listOfThings.Any(t => t.name == "waterbottle" && t.age == 2));
Assert.IsTrue(listOfThings.Any(t => t.name == "pinecone" && t.age == 17));
}
}
try2. I figure out that as I only need IEnumerable then I can just return that.
public IEnumerable<Thing> giveMeAllThings()
{
IList<Thing> listOfThings = new List<Thing>();
Thing thing1 = new Thing { name = "phone", age = 3 };
Thing thing2 = new Thing { name = "waterbottle", age = 2 };
Thing thing3 = new Thing { name = "pinecone", age = 17 };
listOfThings.Add(thing1);
listOfThings.Add(thing2);
listOfThings.Add(thing3);
foreach (Thing t in listOfThings)
yield return t;
}
Edit:
So if I need a List in one method but not another, then the most ‘General’ interface possible to return is an IList:
public IList<Thing> giveMeAllThings()
{
IList<Thing> listOfThings = new List<Thing>();
Thing thing1 = new Thing { name = "phone", age = 3 };
Thing thing2 = new Thing { name = "waterbottle", age = 2 };
Thing thing3 = new Thing { name = "pinecone", age = 17 };
listOfThings.Add(thing1);
listOfThings.Add(thing2);
listOfThings.Add(thing3);
return listOfThings;
}
[TestMethod]
public void UnitTestThings()
{
Thing thing = new Thing();
IEnumerable<Thing> listOfThings = thing.giveMeAllThings();
Assert.AreEqual(3, listOfThings.Count()); // linq count
}
[TestMethod]
public void UnitTestThingsWhereINeedAnActualList()
{
Thing thing = new Thing();
IList<Thing> listOfThings = thing.giveMeAllThings();
Assert.AreEqual(3, listOfThings.Count); // List count
}
The main reason to do this is that, by returning the most “general” purpose interface possible, you have more flexibility in changing your internal implementation to something “better” (ie: more efficient, simpler code, whatever the criteria may be) later, without breaking your public API.
For example, if you switch from
IList<T>toIEnumerable<T>, you could switch your code around to use iterators (yield return) instead of a collection. You may decide that a different collection (instead ofList<T>) works better in your code, and switch to it. If that second collection didn’t implementIList<T>, it would require you to change your public API.