C# 我是否应该始终返回IEnumerable<;T>;而不是IList<;T>;?

C# 我是否应该始终返回IEnumerable<;T>;而不是IList<;T>;?,c#,ienumerable,C#,Ienumerable,当我编写DAL或其他返回一组项的代码时,我是否应该始终使用return语句: public IEnumerable<FooBar> GetRecentItems() public IEnumerable GetRecentItems() 或 public IList GetRecentItems() 目前,在我的代码中,我一直试图尽可能多地使用IEnumerable,但我不确定这是否是最佳实践?这似乎是正确的,因为我返回的是最通用的数据类型,同时仍然描述了它的功能,但这可能不正

当我编写DAL或其他返回一组项的代码时,我是否应该始终使用return语句:

public IEnumerable<FooBar> GetRecentItems()
public IEnumerable GetRecentItems()

public IList GetRecentItems()

目前,在我的代码中,我一直试图尽可能多地使用IEnumerable,但我不确定这是否是最佳实践?这似乎是正确的,因为我返回的是最通用的数据类型,同时仍然描述了它的功能,但这可能不正确。

我认为您可以使用其中任何一种,但每种都有其用途。基本上,
List
IEnumerable
但是您有计数功能,添加元素,删除元素

IEnumerable
对元素计数或获取集合中的特定元素无效

List
是一个集合,非常适合查找特定元素,易于添加或删除元素

一般来说,我尽量使用
List
,因为这给了我更多的灵活性

使用
列出getRecentItems()
而不是
IList GetRecentItems()

列表
为调用代码提供了更多功能,例如修改返回的对象和按索引访问。因此,问题归结为:在应用程序的特定用例中,您是否希望支持此类使用(可能是通过返回新构造的集合!),为了调用者的方便——或者,当调用者只需要在集合中循环,并且您可以安全地返回对真实底层集合的引用,而不必担心这会导致它被错误地更改时,您是否希望在简单的情况下提高速度,等等


只有您能够回答这个问题,并且只有充分了解您的调用者希望如何处理返回值,以及性能在这里有多重要(您要复制的集合有多大,这有多可能成为瓶颈,等等).

当您谈论返回值而不是输入参数时,事情就不那么简单了。当它是一个输入参数时,您确切地知道需要做什么。因此,如果您需要能够遍历集合,则使用IEnumberable,而如果需要添加或删除,则使用IList

在返回值的情况下,它更难。打电话的人期望什么?如果您返回一个IEnumerable,那么他将无法先验地知道他可以从中生成IList。但是,如果您返回一个IList,他将知道可以对其进行迭代。因此,您必须考虑调用方将如何处理数据。您的呼叫方需要/期望的功能是在决定返回什么时应该控制的功能。

这取决于

返回派生最少的类型(
IEnumerable
)将给您留下最大的余地来更改底层实现

返回更派生的类型(
IList
)可以为API用户提供对结果的更多操作


我总是建议返回具有用户需要的所有操作的派生最少的类型。。。因此,基本上,您首先必须在定义的API上下文中取消挖掘对结果的哪些操作是有意义的。

这实际上取决于您使用特定接口的原因

例如,
IList
有几个在
IEnumerable
中没有的方法:

  • IndexOf(T项)
  • 插入(整数索引,T项)
  • RemoveAt(内部索引)
及物业:

  • T这个[int索引]{get;set;}
如果您以任何方式需要这些方法,请务必返回
IList


此外,如果使用您的
IEnumerable
结果的方法期望得到
IList
,它将使CLR不必考虑所需的任何转换,从而优化编译后的代码。

所有人都说这取决于, 如果您不想在调用层添加/删除功能,那么我将投票支持IEnumerable,因为它只提供迭代和基本功能,从设计角度来看,我喜欢这些功能。 我的选票总是反对它,但主要是你喜欢什么,不喜欢什么。
在性能方面,我认为它们是相同的。

< P>一个要考虑的是,如果使用延迟执行LINQ语句来生成<代码> iNeXaby,在从方法返回之前调用<代码> .TistIt()/代码>意味着您的项可以被迭代两次-一次创建列表,当调用者循环通过时,过滤或转换返回值。如果可行,我希望避免将LINQ的结果转换为具体的列表或字典,直到我不得不这样做。如果我的调用者需要一个列表,那就只需要一个简单的方法调用了——我不需要为他们做那个决定,这使得我的代码在调用者只是做foreach的情况下稍微更有效率


我想你们两个都可以用,但每个都有用处。基本上,
List
IEnumerable
,但您有 计数功能、添加元素、删除元素

IEnumerable对于计算元素无效

如果集合是只读的,或者集合的修改由父级
控制,则仅为
计数返回
IList
不是一个好主意

在Linq中,在
IEnumerable
上有一个
Count()
扩展方法,如果基础类型是
IList
,则CLR内的该扩展方法将快捷方式设置为
.Count
,因此性能差异可以忽略不计

一般来说,我觉得(意见)最好尽可能返回IEnumerable,如果需要进行添加,那么将这些方法添加到父类中,否则使用者将管理collectio
public IList<FooBar> GetRecentItems()
public interface IManufacturer 
{
     IEnumerable<Model> Models {get;}
     void AddModel(Model model);
}