当我编写自己的DAL或返回一组项目的其他代码时,我应该始终执行return语句:
public IEnumerable<FooBar> GetRecentItems()
要么
public IList<FooBar> GetRecentItems()
当前,在我的代码中,我一直在尝试尽可能多地使用IEnumerable,但是我不确定这是否是最佳实践吗?这似乎是正确的,因为我在返回最通用的数据类型的同时仍对其功能进行了描述,但这也许是不正确的。
当我编写自己的DAL或返回一组项目的其他代码时,我应该始终执行return语句:
public IEnumerable<FooBar> GetRecentItems()
要么
public IList<FooBar> GetRecentItems()
当前,在我的代码中,我一直在尝试尽可能多地使用IEnumerable,但是我不确定这是否是最佳实践吗?这似乎是正确的,因为我在返回最通用的数据类型的同时仍对其功能进行了描述,但这也许是不正确的。
Answers:
这实际上取决于您为什么使用该特定界面。
例如,IList<T>
有几种方法是不存在的IEnumerable<T>
:
IndexOf(T item)
Insert(int index, T item)
RemoveAt(int index)
和属性:
T this[int index] { get; set; }
如果您以任何方式需要这些方法,那么一定要返回 IList<T>
。
另外,如果使用IEnumerable<T>
结果的方法期望使用IList<T>
,则它将避免考虑任何所需的转换而节省CLR,从而优化了编译后的代码。
框架设计指南建议在需要返回可由调用者或ReadOnlyCollection修改的集合时,使用Collection类。为只读集合的。
之所以比简单IList
更喜欢,是因为IList
它不会通知调用方是否为只读。
如果您返回 IEnumerable<T>
a,则调用者执行某些操作可能会比较棘手。而且,您将不再给调用方提供修改集合的灵活性,而这可能是您可能想要的,也可能是不需要的。
请记住,LINQ包含一些技巧,将根据执行它们的类型来优化某些调用。因此,例如,如果您执行Count
并且基础集合是List,则它将不会遍历所有元素。
就个人而言,对于ORM,我可能会坚持使用它Collection<T>
作为返回值。
通常,您应该要求使用最通用的并返回最具体的信息。因此,如果您有一个采用参数的方法,而您只真正需要IEnumerable中可用的方法,那么那应该是您的参数类型。如果您的方法可以返回IList或IEnumerable,则最好返回IList。这确保了它可以被最广泛的消费者使用。
放宽您的要求,并明确提供您的产品。
那要看...
返回派生最少的类型(IEnumerable
)将使您有最大的回旋余地来改变基础实现。
返回更多派生的类型(IList
)可为您的API用户提供对结果的更多操作。
我总是建议返回包含用户将需要的所有操作的最小派生类型...因此,基本上,您首先必须确定要在定义的API上下文中对结果进行哪些操作才有意义。
要考虑的一件事是,如果您使用延迟执行的LINQ语句生成IEnumerable<T>
,则.ToList()
在从方法返回之前进行调用意味着您的项目可能会重复两次-一次创建List,一次在调用者循环通过时,过滤或转换您的返回值。在可行的情况下,除非需要,否则我希望避免将LINQ-to-Objects的结果转换为具体的List或Dictionary。如果我的调用者需要一个List,则只需一个简单的方法即可调用-我不需要为他们做出决定,这使得我的代码在调用者只是进行foreach的情况下效率更高。
List<T>
为调用代码提供了更多功能,例如修改返回的对象和按索引访问。因此,问题归结为:在应用程序的特定用例中,您是否希望支持此类使用(大概是通过返回一个新构造的集合!),以便调用者方便使用?或者您希望在所有情况下都加快速度?调用者的需求是遍历集合,您可以放心地返回对真实基础集合的引用,而不必担心会错误地更改它,等等?
只有您可以回答这个问题,并且只有充分了解调用者将如何使用返回值,以及此处的性能有多重要(您要复制的集合有多大,这有多大的瓶颈,等等)。
我认为您都可以使用,但是每个都有用。基本上
List
是,IEnumerable
但是您具有计数功能,添加元素,删除元素IEnumerable对元素计数效率不高
如果该集合打算是只读的,或者该集合的修改是由进行控制的,Parent
那么返回一个IList
for Count
并不是一个好主意。
在Linq中,有一个Count()
扩展方法IEnumerable<T>
,.Count
如果基础类型为,则CLR内部将使用该方法进行捷径IList
,因此性能差异可以忽略不计。
通常,我认为(最好)是在可能的情况下返回IEnumerable的更好的做法,如果需要添加,则将这些方法添加到父类中,否则,消费者将在Model内管理违反原则(例如,manufacturer.Models.Add(model)
违反法律的)的集合。得墨meter耳。当然,这些只是准则,而不是一成不变的规则,但是,除非您完全掌握了适用性,否则盲目进行的总比完全不遵循要好。
public interface IManufacturer
{
IEnumerable<Model> Models {get;}
void AddModel(Model model);
}
(注意:如果使用nNHibernate,则可能需要使用其他访问器映射到私有IList。)
正如所有人都说的那样,如果您不希望在调用层添加/删除功能,那么我将投票支持IEnumerable,因为它仅提供迭代和基本功能,在设计上我很喜欢。返回IList我的选票始终是它的主旨,但这主要是您喜欢的和不喜欢的。在性能方面,我认为它们更多的是相同的。