服务接口中的IList,ICollection或IEnumerable?

时间:2017-04-04 08:24:03

标签: c# asp.net-mvc

我正在使用ASP.NET MVC 5中的Entity Framework构建一个访问我的数据库的服务。 所以我首先用他的界面写一个基本服务。但是我担心一件小事。

通常我会在界面中返回IEnumerable<T>,但这通常会导致代码中的ToList()次调用。

所以我想知道在这样的界面中返回的最佳方式是什么。 我可以回复IList,但我担心它可能太多,我不需要IList提供的所有方法。

这是我的代码:

public interface IBaseService<T>
{
    T Add(T obj);
    T Update(T obj);
    T Remove(string id);
    T Get(string id);

    ICollection<T> Find(Expression<Func<bool, T>> func);
    ICollection<T> GetAll();
}

3 个答案:

答案 0 :(得分:5)

你说那个

  

通常我会在界面中返回IEnumerable,但这通常会   导致代码中的ToList()调用。

您必须找到为什么您在结果上调用ToList()。您想要修改结果(添加\删除项目)是可能的,但不太可能。从FindGetAll等方法返回可修改集合通常不是一个好习惯,但您可以返回ICollection<T>IList<T>(如果您还需要快速通过索引器访问或在特定位置插入\ remove。)

然而,您更有可能致电ToList以确定存在多少元素和/或访问特定元素。如果您只需要Count - 请返回IReadOnlyCollection<T>,其IEnumerable<T>仅使用Count属性。如果您还需要通过索引器快速访问 - 请使用索引器返回IReadOnlyList<T> IReadOnlyCollection<T>

ArrayList<T>都实现了所有这些接口,因此您可以按原样返回这些类:

 static IReadOnlyList<string> Test() {
      return new string[0]; // fine
 }

但是,以这种方式返回List时,调用者可能会将其强制转换回IList<T>并仍然对其进行修改。这通常不是问题,但如果你想阻止它,请在列表中使用AsReadOnly(它不会将任何内容复制到新列表中,因此不要担心性能):

static IReadOnlyList<string> Test() {
      return new List<string>().AsReadOnly(); // not required but good practice
 }

答案 1 :(得分:2)

这取决于你的意图。在大多数情况下,您的返回类型可能应为IReadOnlyCollection<T>。在极少数情况下,您希望调用者能够修改集合,您可以返回ICollection<T>。仅当您确定调用者只需要向前迭代时才使用IEnumerable<T>

答案 2 :(得分:1)

我想最纯粹的解决方案是使用IEnumerable<T>,但它归结为在解决方案中设置约定。如果您负责架构,那么您最好还是决定返回List<T>,以便掌握更广泛的方法。