为什么返回接口,例如IEnumerable,IList - 重构的例子

时间:2011-03-06 22:21:24

标签: c#

问题:我是否倒退了这个例子?

返回Interface的原因是:

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。我发现因为我只需要IEnumerable然后我可以返回它。

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;
    }

修改 因此,如果我需要一个方法而不是另一个方法中的List,则可能返回的最“通用”接口是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
    }

3 个答案:

答案 0 :(得分:2)

  

返回Interface的原因是:

这样做的主要原因是,通过返回最“通用”的目的界面,您可以更灵活地将内部实现更改为“更好”(即:更高效,更简单的代码,无论条件如何以后,不要破坏你的公共API。

例如,如果从IList<T>切换到IEnumerable<T>,则可以切换代码以使用迭代器(yield return)而不是集合。您可以决定在代码中使用不同的集合(而不是List<T>),并切换到它。如果第二个集合未实现IList<T>,则需要您更改公共API。

答案 1 :(得分:1)

好吧,您可以返回ICollection<Thing> .CountThing[] .LengthIEnumberable<Thing>,其中包含linq扩展方法{{1} }。如果您只想要元素数,则不一定需要.Count()

使用接口或基本返回类型还显示了如何使用返回类型的意图。

我倾向于在大多数时间使用IList<Thing>

我认为在需要建立索引时会使用数组(或IEnumerable<T>)。

答案 2 :(得分:0)

IEnumerable不如IList特异。我尝试返回仍然有用的最不具体的东西。

假设我正在返回一个IDictionary,那就有回归的诱惑:

IEnumerable<ICollection<KeyValuePair<Key, Value>>

但我认为这并没有准确地描述正在发生的事情,即使它没有特定于:

IDictionary<Key, Value>