关于c#:我的服务应返回什么界面?

What interface should my service return? IQueryable, IList, IEnumerable?

假设我有一个SearchService层,它有一个方法来搜索从某个字符串开始的所有汽车;

1
2
3
4
5
public static class Searcher{
    public IAnInterface<Car> CarsStartingWith(string startWith){
        //magic
    }
}

我的服务应该使用什么接口?iqueryable可以在我的应用程序的其余部分呈现一个良好的流体界面。IEnumerable有一个懒惰的方面。我是最实际的。

为了保持一致性,我希望所有的服务都返回相同的接口,这使得整个过程更加简单。我的回忆也许也是一个选择,但它只提供了那么少的…


我的经验法则如下:

如果我有机会采用例程的核心算法,并以使用yield返回的方式对其进行重构,我将使用IEnumerable

例如,如果我当前的实现在内部使用数组或列表,但我知道,至少在理论上,我可能希望并且能够在内部重新编写它以进行懒惰的评估,那么我将返回IEnumerable。

我发现返回IEnumerable的收益绝对值得使用它。

但是,如果算法本身需要在返回之前对结果进行全面评估(很少,但确实会发生),那么我将使用ilist。基本上,如果我已经在计算它,我会返回它。IList实现了IEnumerable,因此所有与LINQ相关的用例都仍然可以工作,但是您会失去延迟的评估。如果我已经被迫提前评估了,那不是问题。

我很少回宜家。我唯一一次使用这个接口是直接创建一个可查询的数据访问层,或者类似的东西。在大多数情况下,使用这种方法的开销不值得获得收益。

但是,如果您的目标是始终使用单个接口(我不一定同意此目标),我将坚持IEnumerable


我会选择IEnumerable,因为它在框架中有一个更为中心的位置,为需要它的人提供了多功能性,同时也为那些还没有陷入像linq这样的问题的人提供了熟悉性。


除非你有严重的理由不这么做,否则一定要和IEnumerable一起去。然后可以使用yield return实现getter。

IQueryable是一种完全不同的鱼。不是您随便实现的替代典型内存容器的东西。

其余的,IEnumerable和其他的有一个很大的不同:它是只读的。


如果您希望所有的服务返回相同的接口,那么我可能会选择IEnumerable<>

如果需要,您的呼叫者可以很容易地转换为IQueryable或创建List

1
2
3
IEnumerable<Car> cars = Searcher.CarsStartingWith("L");
var carsList = cars.ToList();
var queryableCars = cars.AsQueryable();


简短回答:视情况而定。

更长的回答:返回客户端代码需要的最丰富的类型。在大多数情况下,如果您不需要延迟加载,IList可以工作。仍然可以使用LINQ查询IList或IEnumerable。如果需要延迟加载,则使用IEnumerable或IQueryable。

附带说明:为所有服务返回相同的接口似乎是一个高尚的目标,但是考虑到不同的客户机使用模式,您可能希望返回不同的接口。


IQueryable对它有相当大的要求——例如,您不能返回一个数组。

通常对我来说,在IEnumerableIList之间的选择通常是标准情况下更容易实现的选择。


如果您使用IQueryable作为返回类型,那么您有一个带有泄漏抽象的服务层。