簡體   English   中英

為什么返回接口,例如IEnumerable,IList-重構示例

[英]Why return Interfaces eg IEnumerable, IList - example of refactoring

問題:我是否有這個例子?

返回接口的原因是:

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

編輯:因此,如果我需要一種方法而不是另一種方法的列表,則可能返回的最“常規”接口是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
    }

返回接口的原因是:

這樣做的主要原因是,通過返回最可能的“通用”目的接口,您可以在以后將內部實現更改為“更好”的東西(即:更高效,更簡單的代碼,無論使用何種條件)方面具有更大的靈活性。 ,而不會破壞您的公共API。

例如,如果從IList<T>切換到IEnumerable<T> ,則可以切換代碼以使用迭代器( yield return )而不是集合。 您可能會決定使用其他集合(而不是List<T> )在您的代碼中更好地工作,然后切換到該集合。 如果第二個集合未實現IList<T> ,則將需要您更改公共API。

那么,你可以返回ICollection<Thing>具有.CountThing[]具有.Length ,或IEnumberable<Thing>其具有LINQ擴展方法.Count() 如果只需要元素計數,則不一定需要IList<Thing>

使用接口或基本返回類型還表明了打算如何使用返回類型的意圖。

我傾向於大多數時候使用IEnumerable<T>

我考慮在需要索引時使用數組(或IList<T> )。

IEnumerable比IList不夠具體。 我嘗試返回仍然可以使用的最具體的東西。

假設我要返回IDictionary,那么有返回的誘惑:

IEnumerable<ICollection<KeyValuePair<Key, Value>>

但是,我認為這並不能准確地描述正在發生的事情,盡管它的具體含義不如:

IDictionary<Key, Value>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM